Saturday, January 22, 2011

Enhances gameplay quality through task automation - designed for maximum performance.


// ==UserScript==
// @name           Ikariam Advanced
// @namespace      http://userscripts.org/scripts/show/95128
// @description    Offers task automation - Enhances gameplay quality - Maximum Performance
// @version        1.0
// @include        http://*.ikariam.com/*
// @exclude        http://*.ikariam.com/index.php?view=informations*
// @exclude        http://*.ikariam.com/index.php?view=highscore*
// @exclude        http://*.ikariam.com/index.php?view=options*
// @exclude        http://*.ikariam.com/index.php?view=version*
// @exclude        http://board.*.ikariam.com*
// @exclude        http://*.ikariam.*/board
// ==/UserScript==

/*
 Important note: This script expects the Array prototype to be "clean". It may not work properly if you add your own properties/methods to it.
*/



// Check if Empire Board or ExMachina are being used
$ = document.getElementById;
var EB_used = $("EmpireBoard");
var EM_used = $("IkaScriptSettings_Ikariam_ExMachina");
if(!EB_used && !EM_used)
{try{
/*
 =================================================================================
 =============================== EMPIRE BOARD HERE ====================================
 =================================================================================
*/



/**************************************************************************************************
LAST CHANGES:

Version 2.0.0:
- Fix to fetch resources offers into trading post instead header tooltips.
- Probably support Premium option to double warehouses capacity (not tested, report if work fine).

PREVIOUS CHANGES:
http://feeds.feedburner.com/ikariam-v3-empire-board

Based on "Ikariam Alarm And Overview Table" script (for Ikariam v0.2.8)
http://userscripts.org/scripts/show/35995
**************************************************************************************************/

// Old global vars
var config;
var langtype;
var texts;
var buildings;
var tavernWineUsage = [0, 4, 8, 13, 18, 24, 30, 37, 44, 51, 60, 68, 78, 88, 99, 110, 122, 136,150,165,180,197,216,235,255,277,300,325,351,378,408,439,472,507,544,584,626,670,717,766,818,874,933,995,1060,1129,1202,1278];
var townHallSpaces = [0, 60, 96, 142, 200, 262, 332, 410, 492, 580, 672, 768, 870, 976, 1086, 1200, 1320, 1440, 1566, 1696, 1828, 1964, 2102, 2246, 2390, 2540, 2690, 2845, 3003, 3163, 3326, 3492, 3710, 3880, 4054, 4230, 4410, 4590, 4774, 4960, 5148, 5340, 5532, 5728, 5926, 6126, 6328, 6534, 6760];

var unitsIdClass =  new Object();
// Army
unitsIdClass[303] = 'phalanx';
unitsIdClass[308] = 'steamgiant';
unitsIdClass[315] = 'spearman';
unitsIdClass[302] = 'swordsman';
unitsIdClass[301] = 'slinger';
unitsIdClass[313] = 'archer';
unitsIdClass[304] = 'marksman';
unitsIdClass[307] = 'ram';
unitsIdClass[306] = 'catapult';
unitsIdClass[305] = 'mortar';
unitsIdClass[312] = 'gyrocopter';
unitsIdClass[309] = 'bombardier';
unitsIdClass[310] = 'cook';
unitsIdClass[311] = 'medic';
// Fleet
unitsIdClass[210] = 'ship_ram';
unitsIdClass[211] = 'ship_flamethrower';
unitsIdClass[216] = 'ship_steamboat';
unitsIdClass[213] = 'ship_ballista';
unitsIdClass[214] = 'ship_catapult';
unitsIdClass[215] = 'ship_mortar';
unitsIdClass[212] = 'ship_submarine';

// Old objects
function Resource()
 {
 this.wood  = 0;
 this.wine  = 0;
 this.marble  = 0;
 this.glass  = 0; // For crystal
 this.sulfur  = 0;
 }

// New unique object
if (!EmpireBoard) var EmpireBoard = {};

EmpireBoard =
 {
 /* Requires modules */
 Log:    {},
 DOM:    {},
 Str:    {},
 Ikariam:   {},
 DB:     {},
 Renders:   {},
 Tooltip:   {},
 Handlers:   {},
 Updater:   {},
 
 StartTime:   0,
 EndTime:   0,
 LogEnabled:   false,
 MainID:    'EmpireBoard',
 
 /* Script metas */
 ScriptName:   'Ikariam Empire Board',
 Version:   200,
 HomePage:   '',
 ScriptURL:   '',
 UserScriptsID:  41051
 };

EmpireBoard.Init = function()
 {
 this.StartTime = new Date().getTime();
 this.HomePage   = 'http://userscripts.org/scripts/show/'+this.UserScriptsID;
 this.ScriptURL   = 'http://userscripts.org/scripts/source/'+this.UserScriptsID+'.user.js';
 
 /* Init Log */
 this.Log.Init(this);
 this.Log._Enabled = this.LogEnabled;
 this.Log.Add('Start...');
 
 this.DOM.Init(this);
 this.Str.Init(this);
 this.Ikariam.Init(this);
 this.DB.Init(this);
 this.DB.Load_Options();
 this.Intl.Init(this, this.MainID);
 this.Renders.Init(this);
 this.Tooltip.Init(this, this.MainID+'Tooltip', this.MainID);
 this.Handlers.Init(this);
 //this.Updater.Init(this);
 
 // Always create main div for add-ons  which need to check version
 var body = this.DOM.Get_First_Node("//body");
 if (body != null)
  {
  var div = document.createElement('div');
  div.id = this.MainID;
  div.setAttribute("version", this.Version);
  body.appendChild(div);
  }
 
 this.DB.Load();
 
 this.Intl.SetLanguage(this.DB.Options.Prefs.LANGUAGE);
 this.Intl.Load_LocalizedTexts();
 
 // Str module presets
 this.Str._decimalPoint     = this.Ikariam.LocalizationStrings('decimalPoint');
 this.Str._thousandSeparator    = this.Ikariam.LocalizationStrings('thousandSeperator');
 if (this.Str._decimalPoint == undefined)
  this.Str._decimalPoint = '.';
 if (this.Str._thousandSeparator == undefined)
  this.Str._thousandSeparator = ',';
 this.Str._timeunits_short_day   = this.Ikariam.LocalizationStrings('day','timeunits','short');
 this.Str._timeunits_short_hour   = this.Ikariam.LocalizationStrings('hour','timeunits','short');
 this.Str._timeunits_short_minute  = this.Ikariam.LocalizationStrings('minute','timeunits','short');
 this.Str._timeunits_short_second  = this.Ikariam.LocalizationStrings('second','timeunits','short');
 if (this.Str._timeunits_short_day == undefined)
  this.Str._timeunits_short_day = 'D';
 if (this.Str._timeunits_short_hour == undefined)
  this.Str._timeunits_short_hour = 'h';
 if (this.Str._timeunits_short_minute == undefined)
  this.Str._timeunits_short_minute = 'm';
 if (this.Str._timeunits_short_second == undefined)
  this.Str._timeunits_short_second = 's';
 
 //this.CheckScriptUpdate();
 
 this.FetchData();
 };
 
EmpireBoard.FetchData = function()
 {
 // 1. Global data
 
 // 1.1 current cities
 this.Ikariam.Fetch_CitiesSelect(this.DB.CurrentCities, true);
 // 1.2 gold
 var GoldTitle = this.DOM.Get_First_Node_Title("//div[@id='globalResources']//li[@class='gold']",'?');
 if (GoldTitle != '?')
  {
  config.gold = this.Str.To_Integer(GoldTitle, 0);
  }
 else
  {
  // not connected ?
  }
 this.Log.Add('Gold = '+config.gold);
 
 // 2. Current city data
 
 // 2.1 Current city Id
 
 // 3. Main view data
 
 };
 
EmpireBoard.CheckScriptUpdate = function()
 {
 if ((this.DB.Options['LastCheckUpdate'] == undefined) || (this.DB.Options['LastCheckUpdate'] < this.StartTime - (1000 * 60 * 60 * 24)))
  {
  var self = this;
  var ScriptURL = 'http://userscripts.org/scripts/source/'+this.UserScriptsID+'.meta.js?since='+this.StartTime;
  this.Updater.Check(ScriptURL, function(availableVersion) { self._CompareScriptUpdate(availableVersion); });
  }
 else
  {
  this.Log.Add('Not need check update today');
  }
 };
 
EmpireBoard._CompareScriptUpdate = function(availableVersion)
 {
 this.Log.Add('Available version: '+availableVersion);
 if (availableVersion != 0)
  {
  availableVersion = parseInt(availableVersion);

  if ((availableVersion > this.Version) && ((this.DB.Options['AvailableVersion'] == undefined) || (availableVersion > this.DB.Options['AvailableVersion'])))
   {
   if (confirm("Do you want to install \""+this.ScriptName+"\" v. "+availableVersion+" ?"))
    {
    GM_openInTab(this.ScriptURL+'?version='+availableVersion+'.user.js');
    }
   }
  
  this.DB.Options['AvailableVersion'] = availableVersion;
  this.DB.Options['LastCheckUpdate'] = this.StartTime;
  this.DB.Save_Options();
  }
 };
 
EmpireBoard.ViewIsFinances = function()
 {
 if (this.Ikariam.Is_Version_034x() == true)
  {
  var Cities = this.DB.CurrentCities;
  
  // 1. Sum of population
  var overallPop = 0;
  for (CityId in Cities)
   {
   if (Cities[CityId].own != true) continue;
   var city = getCity(CityId);
   var population = getArrValue(city.buildings['townHall'], 'population', '?');
   
   if (population == '?')
    {
    overallPop = '?';
    break;
    }
   else
    {
    overallPop += parseInt(population);
    }
   }
  
  if (overallPop != '?')
   {
   this.Log.Add('overallPop = '+overallPop);
   
   // 2. Fetch overall Upkeep
   var overallUpkeep = '?';
   var cells = this.DOM.Get_Nodes("//table[@id='upkeepReductionTable'][3]//td[@class='hidden']");
   if (cells.snapshotLength >= 3)
    {
    overallUpkeep = Math.abs(this.Str.To_Integer(cells.snapshotItem(1).textContent,0));
    
    config["upkeeps"]['overall'] = overallUpkeep;
    
    this.Log.Add('overallUpkeep = '+overallUpkeep);
    }
    
   if (overallUpkeep != '?')
    {
    // 3. Fetch and update citizens (gold) production
    // 3.1. Array of cities per name
    var citiesIDs = {};
    var lName = '';
    for (CityId in Cities)
     {
     if (Cities[CityId].own != true) continue;
     var cName = Cities[CityId].name+'';
     citiesIDs[cName] = parseInt(CityId);
     if (lName == cName) this.Ikariam.Insert_Warning("You may choose different names for each cities.",this.ScriptName);
     lName = cName+'';
     }

    // 3.2. Fetch cities table
    var nodes = this.DOM.Get_Nodes("//table[@id='balance']//td[@class='city']");
    for (var i = 0; i < nodes.snapshotLength; i++)
     {
     var node = nodes.snapshotItem(i);
     var cName = this.Str.Trim(node.innerHTML);
     var cID = citiesIDs[cName];
     
     var tr = node.parentNode;
     var tds = tr.getElementsByTagName("td");
     //var tds = tr.childNodes;
     var citizensProd = this.Str.To_Integer(tds[3].innerHTML);
     
     var city = getCity(cID); 
     
     if (city.buildings["townHall"] == undefined) city.buildings["townHall"] = {};
     
     city.buildings["townHall"].citizensProd  = citizensProd;
     this.Log.Add('['+cName+'] (from Finances): citizensProd='+citizensProd);
     }
    
    // 4. Calc shared upkeep for each cities
    for (CityId in Cities)
     {
     if (Cities[CityId].own != true) continue;
     var city = getCity(CityId);
     var population = getArrValue(city.buildings['townHall'], 'population', '?');
     
     if (population != '?')
      {
      var upkeep = Math.ceil(((overallUpkeep*parseInt(population)) / overallPop)-0.6);
      city.buildings["townHall"].upkeep = upkeep;
      this.Log.Add('['+Cities[CityId].name+'] (from Finances): upkeep='+upkeep);
      
      // 5. Calc new income
      var citizensProd = getArrValue(city.buildings['townHall'], 'citizensProd', '?');
      if (citizensProd != '?')
       {
       var incomegold = citizensProd - upkeep;
       city.buildings["townHall"].incomegold = incomegold;
       this.Log.Add('['+Cities[CityId].name+'] (from Finances): incomegold='+incomegold);
       }
      }
     }
    }
   }
  }
 else if (this.Ikariam.Is_Version_033x() == true)
  {
  // Too late to support it, sorry
  }
 else
  {
  var citiesIDs = {};
  var res = this.DOM.Get_Nodes("//select[@id='citySelect']/option");
  for(var i = 0; i < res.snapshotLength; i++)
    {
    var n = res.snapshotItem(i);
    var cName = this.Ikariam.Trim_Coords(n.innerHTML);
    citiesIDs[cName] = parseInt(n.value);
    }
    
  var nodes = this.DOM.Get_Nodes("//table[@id='balance']//td[@class='city']");
  for (var i = 0; i < nodes.snapshotLength; i++)
   {
   var node = nodes.snapshotItem(i);
   var cName = this.Str.Trim(node.innerHTML);
   var cID = citiesIDs[cName];
   
   var tr = node.parentNode;
   var tds = tr.getElementsByTagName("td");
   //var tds = tr.childNodes;
   var incomegold = this.Str.To_Integer(tds[3].innerHTML);
   
   var city = getCity(cID); 
   if (city.buildings["townHall"] == undefined) city.buildings["townHall"] = {};
   city.buildings["townHall"].incomegold  = incomegold;
   }
  }
  
 config.financestime = this.StartTime;
 };
 
EmpireBoard.ViewIsCity = function()
 {
 
 };
 
EmpireBoard.ViewIsBuildingTemple = function()
 {
 var _self = this;
 
 function reportTemple()
  {
  setViewRqTime('finances');
  _self.DB.Save();
  }
 
 var n = document.getElementById("inputWorkersSubmit");
 n.addEventListener("click", reportTemple, false);
 
 var city = getCity(city_idmainView);
 
 var n = document.getElementById("valuePriests");
 city.buildings["temple"].priests = this.Str.To_Integer(n.textContent);
 this.Log.Add('valuePriests = '+city.buildings["temple"].priests);
 };
 
EmpireBoard.ViewIsBuildingAcademy = function()
 {
 var _self = this;
 
 function reportAcademy()
  {
  setViewRqTime('finances');
  _self.DB.Save();
  }
 
 var n = document.getElementById("inputWorkersSubmit");
 n.addEventListener("click", reportAcademy, false);
 
 var city = getCity(city_idmainView);
 
 var n = document.getElementById("valueResearch");
 city.buildings["academy"].Research = this.Str.To_Integer(n.textContent);
 this.Log.Add('valueResearch = '+city.buildings["academy"].Research);
 
 var n = document.getElementById("valueWorkers");
 city.buildings["academy"].scientists = this.Str.To_Integer(n.textContent);
 this.Log.Add('valueWorkers(scientists) = '+city.buildings["academy"].scientists);
 };
 
EmpireBoard.ViewIsBuildingBranchOffice = function()
 {
 var city = getCity(city_idmainView);
 
 var reservedGold =  document.getElementById("reservedGold");
 if (reservedGold != null)
  {
  city.buildings["branchOffice"].reservedGold = this.Str.To_Integer(reservedGold.innerHTML, 0);
  }
 else
  {
  city.buildings["branchOffice"].reservedGold = 0;
  }
  
 // Fetch wood offer
 city.tradewood = 0;
 var selectElt = document.getElementById('resourceTradeType');
 if ((selectElt != null) && (selectElt.value == '444'))
  {
  var inputElt = document.getElementById('resource');
  if ((inputElt != null) && (inputElt.value != '') && (inputElt.value != '0'))
   {
   city.tradewood = this.Str.To_Integer(inputElt.value, 0);
   }
  }
  
 // Fetch wine offer
 city.tradewine = 0;
 var selectElt = document.getElementById('tradegood1TradeType');
 if ((selectElt != null) && (selectElt.value == '444'))
  {
  var inputElt = document.getElementById('tradegood1');
  if ((inputElt != null) && (inputElt.value != '') && (inputElt.value != '0'))
   {
   city.tradewine = this.Str.To_Integer(inputElt.value, 0);
   }
  }
  
 // Fetch marble offer
 city.trademarble = 0;
 var selectElt = document.getElementById('tradegood2TradeType');
 if ((selectElt != null) && (selectElt.value == '444'))
  {
  var inputElt = document.getElementById('tradegood2');
  if ((inputElt != null) && (inputElt.value != '') && (inputElt.value != '0'))
   {
   city.trademarble = this.Str.To_Integer(inputElt.value, 0);
   }
  }
  
 // Fetch crystal offer
 city.tradeglass = 0;
 var selectElt = document.getElementById('tradegood3TradeType');
 if ((selectElt != null) && (selectElt.value == '444'))
  {
  var inputElt = document.getElementById('tradegood3');
  if ((inputElt != null) && (inputElt.value != '') && (inputElt.value != '0'))
   {
   city.tradeglass = this.Str.To_Integer(inputElt.value, 0);
   }
  }
  
 // Fetch sulfur offer
 city.tradesulfur = 0;
 var selectElt = document.getElementById('tradegood4TradeType');
 if ((selectElt != null) && (selectElt.value == '444'))
  {
  var inputElt = document.getElementById('tradegood4');
  if ((inputElt != null) && (inputElt.value != '') && (inputElt.value != '0'))
   {
   city.tradesulfur = this.Str.To_Integer(inputElt.value, 0);
   }
  }
 };
 
EmpireBoard.ViewIsIslandResource = function()
 {
 var cityID = 0;
  
 cityID = this.DOM.Get_First_Node_Value("//form[@id='setWorkers']//input[@name='cityId']",0);
 if (cityID > 0)
  {
  var city = getCity(cityID);
  
  if (city.buildings["townHall"] == undefined) city.buildings["townHall"] = {};
  
  // Fetch wood workers
  var woodworkers = 0;
  var valueWorkers = document.getElementById("valueWorkers");
  if (valueWorkers != null) 
   {
   woodworkers = Number(valueWorkers.textContent);
   }
  
  city.buildings["townHall"].woodworkers = woodworkers;
  this.Log.Add('woodworkers (from Resource)='+woodworkers);
  }
 
 var _self = this;
 
 function reportResource()
  {
  setViewRqTime('finances');
  _self.DB.Save();
  }
 
 var n = document.getElementById("inputWorkersSubmit");
 if (n != null) 
  {
  n.addEventListener("click", reportResource, false);
  }
 };

EmpireBoard.ViewIsIslandTradeGood = function()
 {
 var cityID = 0;
  
 cityID = this.DOM.Get_First_Node_Value("//form[@id='setWorkers']//input[@name='cityId']",0);
 if (cityID > 0)
  {
  var city = getCity(cityID);
  
  if (city.buildings["townHall"] == undefined) city.buildings["townHall"] = {};
  
  // Fetch wood workers
  var specialworkers = 0;
  var valueWorkers = document.getElementById("valueWorkers");
  if (valueWorkers != null) 
   {
   specialworkers = Number(valueWorkers.textContent);
   }
  
  city.buildings["townHall"].specialworkers = specialworkers;
  this.Log.Add('specialworkers (from Resource)='+specialworkers);
  }
 
 var _self = this;
 
 function reportTradegood()
  {
  setViewRqTime('finances');
  _self.DB.Save();
  }
 
 var n = document.getElementById("inputWorkersSubmit");
 if (n != null)
  {
  n.addEventListener("click", reportTradegood, false);
  }
 };
  
EmpireBoard.ViewIsBuildingTavern = function()
 {
 var city = getCity(city_idmainView);
 
 // Old method stop to work...
 /*
 var n = document.getElementById("wineAmount");
 city.wineUsageId = n.selectedIndex;
 city.wineUsage = tavernWineUsage[n.selectedIndex] - getSavedWine();
 */
 // New method Thank  to TorfDrottel 
 var iniValue = 0;
 var scripts = document.getElementsByTagName("script");
 for (var j = 0; j < scripts.length; j++)
  {
  var nScript = scripts[j];
  var sCode = nScript.innerHTML;
  if (sCode.indexOf('create_slider') > 0)
   {
   iniValue = parseInt(/iniValue : (\d+)/.exec(sCode)[1])
   }
  }
 city.wineUsageId = iniValue;
 
 var savedWine = 0;
 if (unsafeWindow && unsafeWindow.savedWine)
  {
  savedWine = unsafeWindow.savedWine[iniValue];
  }
 if ((savedWine == '&nbsp;') || (savedWine == ''))
  {
  savedWine = 0;
  }
 savedWine = Math.round(parseFloat(savedWine));
 var wineUsage = tavernWineUsage[iniValue] - savedWine;
 city.wineUsage = wineUsage;
 
 this.Log.Add('Tavern: iniValue= '+iniValue+', savedWine='+savedWine+', wineUsage='+wineUsage);
 
 var _self = this;

 function storeWineUsage()
  {
  try
   {
   var city_id = _self.DOM.Get_First_Node_Value("//form[@id='wineAssignForm']/input[@type='hidden' and @name='id']");
   var city = getCity(city_id);
   var n = document.getElementById("wineAmount");
   
   var iniValue = n.selectedIndex;
   if (city.wineUsageId != iniValue)
    {
    setViewRqTime('townHall', city_id);
    }
   city.wineUsageId = iniValue;
   
   var savedWine = getSavedWine();
   var wineUsage = tavernWineUsage[iniValue] - savedWine;
   city.wineUsage = wineUsage;
   
   _self.Log.Add('Tavern: iniValue= '+iniValue+', savedWine='+savedWine+', wineUsage='+wineUsage);
   
   _self.DB.Save();
   }
  catch (e)
   {
   }
  }
  
 // Fix for v3
 function getSavedWine() 
  {
  try 
   {
   var n = document.getElementById("savedWine");
   if ((n.innerHTML != '&nbsp;') && (_self.Str.Trim(n.innerHTML) != ''))
    {
    return Math.round(parseFloat(n.innerHTML));
    }
   else return 0;
   }
  catch (e) 
   {
   return 0;
   }
  }
 
 // Soon deprecated
 var n = this.DOM.Get_First_Node("//form[@id='wineAssignForm']//*[@type='submit']");
 n.addEventListener("click", storeWineUsage, false);
 };

EmpireBoard.ViewIsBuildingTownHall = function()
 {
 var city = getCity(city_idmainView);
 
 if (city.buildings["townHall"] == undefined) city.buildings["townHall"] = {};

 var population = 0;
 population = Number(this.DOM.Get_First_Node_TextContent("//li[contains(@class, 'space')]/span[contains(@class, 'occupied')]", "0"));
 city.buildings["townHall"].population = population;
 //city.population = population; // Soon deprecated
 
 // May use happiness than growth...
 city.buildings["townHall"].growth = this.Str.To_Float(this.DOM.Get_First_Node_TextContent("//li[contains(@class, 'growth')]/span[@class='value']", "0"),'?',this.Ikariam.LocalizationStrings('decimalPoint'));
 this.Log.Add('Growth (from TownHall)='+city.buildings["townHall"].growth);
 
 city.buildings["townHall"].happiness  = Number(this.DOM.Get_First_Node_TextContent("//div[contains(@class, 'happiness')]/div[@class='value']", "0")) + city.buildings["townHall"].population;

 city.buildings["townHall"].bonusspace = Number(this.DOM.Get_First_Node_TextContent("//li[contains(@class, 'space')]/span[contains(@class, 'total')]", "0")) - townHallSpaces[getBuildingLevel(city_idmainView, 'townHall', 1, 0)];
 
 // Fetch citizens
 var citizens = 0;
 citizens = Number(this.DOM.Get_First_Node_TextContent("//div[contains(@class, 'citizens')]//span[@class='count']", "0"));
 city.buildings["townHall"].citizens = citizens;
 this.Log.Add('citizens (from TownHall)='+citizens);
 
 // Fetch wood workers
 var woodworkers = 0;
 woodworkers = Number(this.DOM.Get_First_Node_TextContent("//div[contains(@class, 'woodworkers')]//span[@class='count']", "0"));
 city.buildings["townHall"].woodworkers = woodworkers;
 this.Log.Add('woodworkers (from TownHall)='+woodworkers);
 
 // Fetch good workers
 var specialworkers = 0;
 specialworkers = Number(this.DOM.Get_First_Node_TextContent("//div[contains(@class, 'specialworkers')]//span[@class='count']", "0"));
 city.buildings["townHall"].specialworkers = specialworkers;
 this.Log.Add('specialworkers (from TownHall)='+specialworkers);
 
 // Fetch scientist
 var scientists = 0;
 scientists = Number(this.DOM.Get_First_Node_TextContent("//div[contains(@class, 'scientists')]//span[@class='count']", "0"));
 if ((scientists > 0) || (city.buildings["academy"] != undefined))
  {
  if (city.buildings["academy"] == undefined) city.buildings["academy"] = {};
  city.buildings["academy"].scientists = scientists;
  }
 this.Log.Add('scientists (from TownHall)='+scientists);
 
 // Fetch priests
 if (this.Ikariam.Is_Version_032x() == true)
  {
  var priests = 0;
  priests = Number(this.DOM.Get_First_Node_TextContent("//div[contains(@class, 'priests')]//span[@class='count']", "0"));
  if ((priests > 0) || (city.buildings["temple"] != undefined))
   {
   if (city.buildings["temple"] == undefined) city.buildings["temple"] = {};
   city.buildings["temple"].priests = priests;
   }
  this.Log.Add('priests (from TownHall)='+priests);
  }

 var citizensProd = 0;
 citizensProd = this.Str.To_Integer(this.DOM.Get_First_Node_TextContent("//div[@class='citizens']/span[@class='production']", "0"),0);
 city.buildings["townHall"].citizensProd = citizensProd;
 this.Log.Add('citizensProd (from TownHall)='+citizensProd);
 
 if (this.Ikariam.Is_Version_035x() == true)
  {
  
  }
 else
  {
  var incomegold = 0;
  incomegold = Number(this.DOM.Get_First_Node_TextContent("//li[contains(@class, 'incomegold')]/span[@class='value']", "0"));
  city.buildings["townHall"].incomegold = incomegold;
  this.Log.Add('IncomeGold (from TownHall)='+incomegold);

  var upkeep = citizensProd - incomegold;
  city.buildings["townHall"].upkeep = upkeep;
  this.Log.Add('Upkeep (from TownHall)='+upkeep);
  }
 };
 
EmpireBoard.ViewIsResearchAdvisor = function()
 {
 var _self = this;
 
 function reportResearch()
  {
  setViewRqTime('researchOverview');
  _self.DB.Save();
  }
 
 var rButtons = this.DOM.Get_Nodes("//ul[@class='researchTypes']//div[@class='researchButton']//a[contains(@class, 'build')]");
 this.Log.Add("Research buttons: "+rButtons.snapshotLength);
 if (rButtons.snapshotLength > 0)
  {
  for (var i=0; i < rButtons.snapshotLength; i++)
   {
   var rButton = rButtons.snapshotItem(i);
   //rButton.href='';
   rButton.addEventListener("click", reportResearch, false);
   }
  }
 };

// Thank to matteo466
EmpireBoard.ViewIsResearchOverview = function()
 {
 this.Log.Add('Fetch discovered research...');
 
 config["research"] = {};
 

 var LIs = this.DOM.Get_Nodes("//div[@id='mainview']//div[contains(@class, 'content')]//li[@class='explored']");
 this.Log.Add("Research explored: "+LIs.snapshotLength);
 if (LIs.snapshotLength > 0)
  {
  for (var i=0; i < LIs.snapshotLength; i++)
   {
   var researchLI = LIs.snapshotItem(i);
   var researchA = researchLI.getElementsByTagName("a")[0];
   var resReg = /[\?&]{1}researchId=([0-9]+)&?/i.exec(researchA.href);
   if (resReg != null)
    {
    var researchID = parseInt(resReg[1]);
    var researchLevel = this.Str.To_Integer(researchA.textContent.replace(/\-/g, ""),1);
    
    this.Log.Add("Found research: "+researchID+', level '+researchLevel);
    
    config["research"][researchID] = {};
    config["research"][researchID].Explored = true;
    config["research"][researchID].Level = researchLevel;
    }
   }
  }
 
 function isExplored(researchID)
  {
  if ((config["research"][researchID] != undefined) && (config["research"][researchID].Explored == true))
   return true;
  else
   return false;
  }
 
 var FleetUpkeepBonus = 0;
 if (isExplored(1020)) FleetUpkeepBonus += 2;
 if (isExplored(1050)) FleetUpkeepBonus += 4;
 if (isExplored(1090)) FleetUpkeepBonus += 8;
 if (isExplored(1999))
  {
  FleetUpkeepBonus += 2*config["research"][1999].Level;
  }
 this.Log.Add("FleetUpkeepBonus: "+FleetUpkeepBonus);
 config["research"].FleetUpkeepBonus = FleetUpkeepBonus;
 
 var ArmyUpkeepBonus = 0;
 if (isExplored(4020)) ArmyUpkeepBonus += 2;
 if (isExplored(4050)) ArmyUpkeepBonus += 4;
 if (isExplored(4090)) ArmyUpkeepBonus += 8;
 if (isExplored(4999))
  {
  ArmyUpkeepBonus += 2*config["research"][4999].Level;
  }
 this.Log.Add("ArmyUpkeepBonus: "+ArmyUpkeepBonus);
 config["research"].ArmyUpkeepBonus = ArmyUpkeepBonus;
 
 var ResearchCost = 6;
 if (isExplored(3110)) ResearchCost -= 3;
 this.Log.Add("ResearchCost: "+ResearchCost);
 config["research"].ResearchCost = ResearchCost;
 
 var ResearchBonus = 0;
 if (isExplored(3020)) ResearchBonus += 2;
 if (isExplored(3050)) ResearchBonus += 4;
 if (isExplored(3090)) ResearchBonus += 8;
 if (isExplored(3999))
  {
  ResearchBonus += 2*config["research"][3999].Level;
  }
 this.Log.Add("ResearchBonus: "+ResearchBonus);
 config["research"].ResearchBonus = ResearchBonus;
 
 config["research"].uptime = this.StartTime;
 };
 
EmpireBoard.ViewIsPremium = function()
 {
 config["premium"] = {};
 
 var TRs = this.DOM.Get_Nodes("//div[@id='premiumOffers']//table[contains(@class, 'TableHoriMax')]//tr");
 this.Log.Add("premiumOffers rows: "+TRs.snapshotLength);
 
 // fetch savecapacityBonus remaining time
 var savecapacityBonus = TRs.snapshotItem(20).getElementsByTagName("td")[0];
 if (this.DOM.Has_ClassName(savecapacityBonus,'active') == true)
  {
  var remainingTime = 0;
  var remainingText = savecapacityBonus.textContent;
  var regExp = new RegExp("([0-9])\\s+([a-z])", "ig");
  var RegExpRes = regExp.exec(remainingText);
  if (RegExpRes != null)
   {
   var timeValue = parseInt(RegExpRes[1]);
   var timeUnit = RegExpRes[2];
   
   if (timeUnit == this.Ikariam.LocalizationStrings('day','timeunits','short'))
    {
    remainingTime = timeValue*24*60*60*1000;
    }
   else if (timeUnit == this.Ikariam.LocalizationStrings('hour','timeunits','short'))
    {
    remainingTime = timeValue*60*60*1000;
    }
   else if (timeUnit == this.Ikariam.LocalizationStrings('minute','timeunits','short'))
    {
    remainingTime = timeValue*60*1000;
    }
   else if (timeUnit == this.Ikariam.LocalizationStrings('second','timeunits','short'))
    {
    remainingTime = timeValue*1000;
    }
   else
    {
    remainingTime = 24*60*60*1000;
    }
   }
  else
   {
   remainingTime = 24*60*60*1000;
   }
  this.Log.Add("savecapacityBonus: remainingTime="+remainingTime+", timeValue="+timeValue+", timeUnit="+timeUnit);
  config["premium"].savecapacityBonus = this.StartTime + remainingTime;
  }
 
 // fetch storagecapacityBonus remaining time
 var storagecapacityBonus = TRs.snapshotItem(23).getElementsByTagName("td")[0];
 if (this.DOM.Has_ClassName(storagecapacityBonus,'active') == true)
  {
  var remainingTime = 0;
  var remainingText = storagecapacityBonus.textContent;
  var regExp = new RegExp("([0-9])\\s+([a-z])", "ig");
  var RegExpRes = regExp.exec(remainingText);
  if (RegExpRes != null)
   {
   var timeValue = parseInt(RegExpRes[1]);
   var timeUnit = RegExpRes[2];
   
   if (timeUnit == this.Ikariam.LocalizationStrings('day','timeunits','short'))
    {
    remainingTime = timeValue*24*60*60*1000;
    }
   else if (timeUnit == this.Ikariam.LocalizationStrings('hour','timeunits','short'))
    {
    remainingTime = timeValue*60*60*1000;
    }
   else if (timeUnit == this.Ikariam.LocalizationStrings('minute','timeunits','short'))
    {
    remainingTime = timeValue*60*1000;
    }
   else if (timeUnit == this.Ikariam.LocalizationStrings('second','timeunits','short'))
    {
    remainingTime = timeValue*1000;
    }
   else
    {
    remainingTime = 24*60*60*1000;
    }
   }
  else
   {
   remainingTime = 24*60*60*1000;
   }
  this.Log.Add("storagecapacityBonus: remainingTime="+remainingTime+", timeValue="+timeValue+", timeUnit="+timeUnit);
  config["premium"].storagecapacityBonus = this.StartTime + remainingTime;
  }
 };
 
EmpireBoard.ViewIsActionTransport = function()
 {
 // Todo
 };
 
EmpireBoard.ViewIsActionDeployment = function()
 {
 // Todo
 };
 
EmpireBoard.ViewIsActionPlunder = function()
 {
 // Todo
 };
 
EmpireBoard.ViewIsActionBlockade = function()
 {
 // Todo
 };
 
EmpireBoard.ViewIsActionOccupy = function()
 {
 // Todo
 };
 
EmpireBoard.ViewIsActionDefendCity = function()
 {
 // Todo
 };
 
EmpireBoard.ViewIsActionDefendPort = function()
 {
 // Todo
 };
 
EmpireBoard.ViewIsMerchantNavy = function()
 {
 var _self = this;
 var MerchantTimes = {};
 this.Ikariam.Fetch_MerchantNavy_Boxes(this.DB.MerchantBoxes, true);
 this.Ikariam.Fetch_TimeCounters(MerchantTimes,'getCountdown');
 
 config["transports"] = {};
 
 function addTransport(cityID, transportID, endTime)
  {
  if (config["transports"][cityID] == undefined) config["transports"][cityID] = {};
  if (config["transports"][cityID][transportID] == undefined) config["transports"][cityID][transportID] = {};
  config["transports"][cityID][transportID].endTime = endTime;
  
  _self.Log.Add('Transport['+transportID+'] from oCityId='+cityID+' while '+_self.Str.FormatRemainingTime(endTime-_self.StartTime));
  }
 
 var boxId;
 for (boxId in this.DB.MerchantBoxes)
  {
  if (this.DB.MerchantBoxes[boxId].missions != undefined)
   {
   var missionId;
   for (missionId in this.DB.MerchantBoxes[boxId].missions)
    {
    var oCityId = this.DB.MerchantBoxes[boxId].missions[missionId].oCityId;
    if (oCityId > 0)
     {
     var endTime = 0;
     
     var ETA = this.DB.MerchantBoxes[boxId].missions[missionId].ETA;
     var ETAtime = 0;
     if ((ETA != '') && (MerchantTimes[ETA] != undefined))
      {
      ETAtime = this.StartTime + (MerchantTimes[ETA].enddate - MerchantTimes[ETA].currentdate);
      }
     if (ETAtime > 0) endTime = ETAtime;
      
     var RETtime = 0;
     var RET = this.DB.MerchantBoxes[boxId].missions[missionId].RET;
     if ((RET != '') && (MerchantTimes[RET] != undefined))
      {
      RETtime = this.StartTime + (MerchantTimes[RET].enddate - MerchantTimes[RET].currentdate);
      }
     if ((RETtime > 0) && (RETtime > endTime)) endTime = RETtime;
     
     if (endTime <= 0)
      endTime = this.StartTime + (1 * 20 * 60 * 1000);
     
     addTransport(oCityId, missionId, endTime);
     }
    }
   }
  }
 };
 
EmpireBoard.ViewIsMilitaryMovements = function()
 {
 config["movements"] = {};
 function addMovement(cityID, movementID, FleetMovement)
  {
  if (config["movements"][cityID] == undefined) config["movements"][cityID] = {};
  if (config["movements"][cityID][movementID] == undefined) config["movements"][cityID][movementID] = {};

  config["movements"][cityID][movementID] = FleetMovement;
  config["movements"][cityID][movementID].endTime = FleetMovement.time;
  }
  
 config["attacks"] = {};
 function addAttacks(cityID, movementID, FleetMovement)
  {
  if (config["attacks"][cityID] == undefined) config["attacks"][cityID] = {};
  if (config["attacks"][cityID][movementID] == undefined) config["attacks"][cityID][movementID] = {};

  config["attacks"][cityID][movementID] = FleetMovement;
  config["attacks"][cityID][movementID].endTime = FleetMovement.time;
  }
 
 this.Ikariam.Fetch_FleetMovements(this.DB.FleetMovements);
 
 var resMi = this.DOM.Get_Nodes("//div[@id='fleetMovements']//table[contains(@class, 'locationEvents')]/tbody/tr/td/img[contains(@src, 'mission_')]");
 if (resMi.snapshotLength > 0)
  {
  for (var i=0; i < resMi.snapshotLength; i++)
   {
   var tr = resMi.snapshotItem(i).parentNode.parentNode;
   var tds = tr.getElementsByTagName("td");
   //var tds = tr.childNodes;
    
   var fleetId = tds[1].id;
   
   if ((fleetId != '') && (this.DB.FleetMovements[fleetId] != undefined))
    {
    var FleetMovement = this.DB.FleetMovements[fleetId];
    var toOwn = false;
    if ((this.DB.CurrentCities[FleetMovement.tCityId] != undefined) && (FleetMovement.tCityId != FleetMovement.oCityId) && (this.DB.CurrentCities[FleetMovement.tCityId].own == true))
     {
     toOwn = true;
     }
    
    // Values: deployarmy, deployfleet, plunder, blockade, defend, defend_port, trade, transport, occupy
    if (FleetMovement.hostile == true)
     {
     addAttacks(FleetMovement.tCityId, fleetId, FleetMovement);
     }
    else if (FleetMovement.own == true)
     {
     if (FleetMovement.mission == 'trade')
      {
      // Not military movement
      }
     else if (FleetMovement.mission == 'transport')
      {
      // Not military movement
      if ((FleetMovement.hasAction == true) && (FleetMovement.hasGoods == true) && (FleetMovement.toLeft == false) && (FleetMovement.toRight == false) && (toOwn == true))
       {
       setViewRqTime('merchantNavy',0,FleetMovement.time);
       }
      }
     else if (FleetMovement.mission == 'deployarmy')
      {
      addMovement(FleetMovement.oCityId, fleetId, FleetMovement);
      
      if ((FleetMovement.toRight == true) && (toOwn == true))
       {
       this.Log.Add("Army "+fleetId+" will arrive to city["+FleetMovement.tCityId+"]");
       setViewRqTime('cityMilitary-army', FleetMovement.tCityId, FleetMovement.time);
       }
      else if (FleetMovement.toLeft == true)
       {
       this.Log.Add("Army "+fleetId+" come back to city["+FleetMovement.oCityId+"]");
       setViewRqTime('cityMilitary-army', FleetMovement.oCityId, FleetMovement.time);
       }
      }
     else if (FleetMovement.mission == 'deployfleet')
      {
      addMovement(FleetMovement.oCityId, fleetId, FleetMovement);
      
      if ((FleetMovement.toRight == true) && (toOwn == true))
       {
       this.Log.Add("Fleet "+fleetId+" will arrive to city["+FleetMovement.tCityId+"]");
       setViewRqTime('cityMilitary-fleet', FleetMovement.tCityId, FleetMovement.time);
       }
      else if (FleetMovement.toLeft == true)
       {
       this.Log.Add("Fleet "+fleetId+" come back to city["+FleetMovement.oCityId+"]");
       setViewRqTime('cityMilitary-fleet', FleetMovement.oCityId, FleetMovement.time);
       }
      }
     else if (FleetMovement.mission == 'plunder')
      {
      addMovement(FleetMovement.oCityId, fleetId, FleetMovement);
      
      if ((FleetMovement.hasGoods == true) && (FleetMovement.toLeft == false) && (FleetMovement.toRight == false))
       {
       setViewRqTime('merchantNavy',0,FleetMovement.time);
       }
      }
     else if (FleetMovement.mission == 'blockade')
      {
      addMovement(FleetMovement.oCityId, fleetId, FleetMovement);
      }
     else
      {
      addMovement(FleetMovement.oCityId, fleetId, FleetMovement);
      }
     }
    else
     {
     if (FleetMovement.mission == 'trade')
      {
      if ((toOwn == true) && (FleetMovement.toRight == true))
       {
       this.Log.Add("Foreign transport "+fleetId+" arrive to city["+FleetMovement.tCityId+"]");
       setViewRqTime('branchOffice', FleetMovement.tCityId, FleetMovement.time);
       }
      }
     else if (FleetMovement.mission == 'transport')
      {
      if ((toOwn == true) && (FleetMovement.toRight == true))
       {
       this.Log.Add("Foreign transport "+fleetId+" arrive to city["+FleetMovement.tCityId+"]");
       setViewRqTime('', FleetMovement.tCityId, FleetMovement.time);
       }
      }
     }
    }
   }
  }
  
 config.mAMMtime = this.StartTime;
 };
 
EmpireBoard.ViewIsBuildingWorkshop = function()
 {
 var scripts = document.getElementsByTagName("script");
 var found = false;
 var sCode = '';
 for (var j = 0; j < scripts.length; j++)
  {
  // search upgradeCountDown
  var nScript = scripts[j];
  sCode = nScript.innerHTML;
  if (sCode.indexOf('upgradeCountdown') >= 0)
   {
   found = true;
   break;
   }
  }
 if (found == true)
  {
  // buildings under upgrading
  var enddate = 0;
  var currentdate = 0;
  if (/enddate[^0-9]*([0-9]+)/.exec(sCode) != null)
   {
   enddate = parseFloat(RegExp.$1) * 1000; 
   }
  if (/currentdate[^0-9]*([0-9]+)/.exec(sCode) != null)
   {
   currentdate = parseFloat(RegExp.$1) * 1000; 
   }
  if (enddate != 0 && currentdate != 0)
   {
   setViewRqTime('workshop', city_idmainView, this.StartTime + (enddate - currentdate), true);
   this.Log.Add('Workshop upgrade remaining time: '+enddate+' - '+currentdate+' = '+(enddate-currentdate)/1000+'s');
   }
  }
 };
 
EmpireBoard.DB =
 {
 _Parent:    null,
 Prefix:     '',
 CurrentCities:   {},
 FleetMovements:   {},
 MerchantBoxes:   {},
 Options:    {}
 };

EmpireBoard.DB.Init = function(parent, host)
 {
 this._Parent = parent;
 if (host == undefined) host = this._Parent.Ikariam.Host();
 
 var prefix = host;
 prefix = prefix.replace('.ikariam.', '-');
 prefix = prefix.replace('.', '-');
 this.Prefix = prefix;
 };
  
EmpireBoard.DB.Serialize = function(data)
 {
 return uneval(data);
 };

EmpireBoard.DB.UnSerialize = function(data)
 {
 return eval(data);
 };
 
function getVar(varname, vardefault) {
  var res = GM_getValue(EmpireBoard.Ikariam.Host()+varname);
  if (res == undefined) {
    return vardefault;
  }
  return res;
}

function setVar(varname, varvalue) {
  GM_setValue(EmpireBoard.Ikariam.Host()+varname, varvalue);
}

EmpireBoard.DB.Load = function()
 {
 config = this.UnSerialize(getVar("config", ""));
 if (config == null || config == undefined || config == "" || ("".config == "NaN"))
  {
  config = new Object();
  }
 
 // Set dbversion for migrate agent
 if (config["dbversion"] == undefined)   config["dbversion"]  = this._Parent.Version-1;
 
 // Check if main arrays exists
 if (config["unitnames"] == undefined)   config["unitnames"]  = {};
 if (config["upkeeps"] == undefined)    config["upkeeps"]   = {};
 if (config["arrivinggoods"] == undefined)  config["arrivinggoods"] = {};
 if (config["movements"] == undefined)   config["movements"]  = {};
 if (config["attacks"] == undefined)    config["attacks"]   = {};
 if (config["transports"] == undefined)   config["transports"]  = {};
 if (config["research"] == undefined)   config["research"]   = {};
 
 if (config["dbversion"] < this._Parent.Version)
  {
  this.MigrateAgent();
  }
 };
 
EmpireBoard.DB.MigrateAgent = function()
 {
 this._Parent.Log.Add('Apply Migrate Agent to DB v. '+config["dbversion"]);
 
 config["dbversion"] = this._Parent.Version;
 };
 
EmpireBoard.DB.GarbageCollector = function()
 {
 var ConfigIds = '';
 var ConfigId;
 for (ConfigId in config)
  {
  var toDelete = false;
  switch(ConfigId)
   {
   case 'unitnames':
   case 'upkeeps':
   case 'movements':
   case 'attacks':
   case 'transports':
   case 'research':
   case 'premium':
   case 'gold':
   case 'merchantNavyrqtime':
   case 'merchantNavytime':
   case 'financestime':
   case 'financesrqtime':
   case 'mAMMtime':
   case 'mAMMrqtime':
    toDelete = false;

    break;
   
   case 'arrivinggoods':
    var oCityId;
    for (oCityId in config['arrivinggoods'])
     {
     if (this.CurrentCities[oCityId] == undefined)
      {
      if (delete config['arrivinggoods'][oCityId])
       this._Parent.Log.Add('Garbage collector has removed arrivinggoods of unkown city['+oCityId+']');
      }
     }
    toDelete = false;
    break;
 
   case 'cfg':
    toDelete = true;
    break;
   
   default:
    // Check if old city
    var CityId = this._Parent.Str.To_Integer(ConfigId,'NaN');
    if (CityId != 'NaN')
     {
     if (this.CurrentCities[CityId] == undefined)
      {
      toDelete = true;
      }
     else
      {
      toDelete = false;
      var ConfigSubIds = '';
      var ConfigSubId;
      for (ConfigSubId in config[ConfigId])
       {
       var subToDelete = false;
       switch(ConfigSubId)
        {
        case 'crystal':
        case 'underConstruction':
        case 'population':
        case 'citizens':
         subToDelete = true;
         break
        
        default:
         break;
        }
       if (subToDelete == true)
        {
        if (delete config[ConfigId][ConfigSubId])
         ConfigSubIds += ' '+ConfigSubId;
        }
       }
      if (ConfigSubIds != '') this._Parent.Log.Add('Garbage collector has removed city['+ConfigId+'] properties:'+ConfigSubIds);
      }
     }
    break;
   }
  
  if (toDelete == true)
   {
   if (delete config[ConfigId])
    ConfigIds += ' '+ConfigId;
   }
  }
 
 if (ConfigIds != '') this._Parent.Log.Add('Garbage collector has removed array:'+ConfigIds);
 };

EmpireBoard.DB.Save = function()
 {
 setVar("config", this.Serialize(config));
 };

EmpireBoard.DB.Load_Options = function()
 {
 // Not used yet
 this.Options = this.UnSerialize(GM_getValue(this.Prefix+'.Opt', false)) || {};
 
 if (this.Options.Prefs == undefined)      this.Options.Prefs = {};
 if (this.Options.Prefs.TABLE_RESOURCES == undefined)  this.Options.Prefs.TABLE_RESOURCES = true;
 if (this.Options.Prefs.TABLE_BUILDINGS == undefined)  this.Options.Prefs.TABLE_BUILDINGS = true;
 if (this.Options.Prefs.TABLE_ARMYFLEET == undefined)  this.Options.Prefs.TABLE_ARMYFLEET = true;
 if (this.Options.Prefs.PROGRESS_BAR_MODE == undefined)  this.Options.Prefs.PROGRESS_BAR_MODE = 'time';
 if (this.Options.Prefs.LANGUAGE == undefined)    this.Options.Prefs.LANGUAGE = '';
 };

EmpireBoard.DB.Save_Options = function()
 {
 GM_setValue(this.Prefix+'.Opt', this.Serialize(this.Options));
 };
 
EmpireBoard.Renders =
 {
 _Parent:    null
 };

EmpireBoard.Renders.Init = function(parent)
 {
 this._Parent = parent;
 };
 
function createLink(text, href, attrs)
 {
 return "<a href=\""+href+"\" "+attrs+">"+text+"</a>";
 }

EmpireBoard.Renders.Buildings_Table_Content = function()
 {
 var s = '';
 var Cities = this._Parent.DB.CurrentCities;
 
 // Array use to group buildings
 var orderedBuildings = this._Parent.Ikariam.BuildingsList();
 
 function getBuildingCount(city_id, name, defaultValue)
  {
  if (defaultValue == undefined) defaultValue = 0;
  var count = 0;
  var city = getCity(city_id);
  
  if ((city.buildings == undefined) || (city.buildings[name] == undefined))
   {
   if (name == 'townHall') count = 1;
   }
  else if (city.buildings[name].levels != undefined)
   {
   var p;
   for (p in city.buildings[name].levels)
    {
    count++;
    }
   }
  else if (city.underConstructionName == name)
   {
   count = 1;
   }
  
  if (count == 0) count = defaultValue;
  return count;
  }
 
 // Search buildings used
 var CityId;
 var buildingsCount = [];
 for (CityId in Cities)
  {
  if (Cities[CityId].own != true) continue;
  for (key in orderedBuildings)
   {
   var count = getBuildingCount(CityId, key, 0);
   if (buildingsCount[key] == undefined || buildingsCount[key] < count)
    {
    buildingsCount[key] = count;
    }
   }
  }
 
 s += "<table class='Overview Buildings'>";
 
 // Table header
 s += "<thead><tr><th class='city_name' nowrap>"+this._Parent.Intl.TT("cityName")+"</th>";
 s += "<th class='actions' nowrap>"+this.Buildings_HeaderIcons(current_city_id)+"</th>";
 var firstStyle = '';
 var buildsNum = 0;
 var lastTopic = '';
 for (key in orderedBuildings) 
  {
  if (buildingsCount[key] > 0)
   {
   var colspan = (buildingsCount[key] > 1) ? ' colspan='+buildingsCount[key] : '';
   if (lastTopic != orderedBuildings[key]) { firstStyle = "lf"; } else { firstStyle = ""; }
   s += "<th"+colspan+" building='"+key+"' class='"+firstStyle+" build_name"+buildingsCount[key]+" "+key+"' nowrap "+createTooltipAttribute(this._Parent.Intl.TT(key,'buildings'))+">"+
    this._Parent.Intl.TT(key,'buildings_short')+
    "</th>";
   lastTopic = orderedBuildings[key];
   buildsNum++;
   }
  }
 if (buildsNum <= 1) s += "<th class='lf'></th><th></th><th></th><th></th><th></th><th></th>";
 s += "</tr></thead>";
 
 s += "<tbody>";
 
 function createLinkToCityView(city_id)
  {
  var rHTML = '';
  rHTML += '<a href="?view=city&cityId='+city_id+'" class="changeCity" cityid="'+city_id+'" title="View city"><img align="absmiddle" src="skin/layout/icon-city2.gif" /></a>';
  if (reportViewToSurvey('city', city_id) == '!')
   {
   rHTML += '<sup class=Red title="Require attention">!</sup>';
   }
  else
   {
   rHTML += '&nbsp;';
   }
  return rHTML;
  }

 function getBuildingLink(city_id, name, defaultValue, position)
  {
  if (defaultValue == undefined) defaultValue = '';
  if (position == undefined)
   {
   position = -1;
   if (name == 'townHall') position = 0;
   }
  var link = '';
  
  if (position == -1)
   {
   // will deprecated
   var city = getCity(city_id);
   link = getArrValue(city.buildings[name], "link", defaultValue);
   }
  else
   {
   link = '?view='+name+'&id='+city_id+'&position='+position;
   }
  
  if (link == '') link = defaultValue;
  return link;
  }

 var CityId;
 var i = 0;
 var odd = '';
 for (CityId in Cities)
  {
  if (Cities[CityId].own != true) continue;
  var city = getCity(CityId);
  
  var trclass = (parseInt(current_city_id) == parseInt(CityId)) ? "current" : "";
  s += "<tr class='"+odd+" "+trclass+"' cityid='"+CityId+"' islandid='"+city.island_id+"' coord='"+city.city_coord+"'>";
  
  var usedspaces = getCityBuildingsCount(CityId, 0);
  s += "<td class='city_name' nowrap>"+createLinkToChangeCity(Cities[CityId].name, CityId, i, (usedspaces > 0) ? 15-usedspaces : '', 'Green', 'Available free spaces')+"</td>";
  s += "<td class='actions' nowrap>"+createLinkToCityView(CityId)+"</td>";
  
  var firstStyle = '';
  var lastTopic = '';
  for (key in orderedBuildings)
   {
   if (buildingsCount[key] > 0)
    {
    if (lastTopic != orderedBuildings[key]) { firstStyle = "lf"; } else { firstStyle = ""; }
    
    var buildingCount = 0;
    if (city.buildings[key] != undefined)
     {
     if (city.buildings[key].levels == undefined)
      {
      // soon deprecated
      city.buildings[key].levels = {};
      var position = getBuildingPosition(parseInt(CityId), key, -1);
      var level = getBuildingLevel(parseInt(CityId), key, 0, position);
      city.buildings[key].levels[position] = level;
      }
     
     var position;
     for (position in city.buildings[key].levels)
      {
      var currentBuildingStyle = "";
      if ((key == this._Parent.Ikariam.View()) && (parseInt(CityId) == city_idmainView) && (position == city_positionmainView))
       {
       currentBuildingStyle = " Bold current";
       }

      var level = getBuildingLevel(parseInt(CityId), key, '-', position);
      if (level == undefined || level == "" || level == 0)
       {
       level = "-";
       }

      var link = getBuildingLink(parseInt(CityId), key, '-', position);

      if ((city.underConstructionName == key) && (city.underConstructionPosition == position))
       {
       if (level == "-") { level = 0; }
       var underConstructionTime = city.underConstructionTime;
       // deprecated
       //if (underConstructionTime == undefined) underConstructionTime = city.underConstruction.split(",")[1];
       var sdate = smartDateFormat(underConstructionTime);
       if (underConstructionTime <= this._Parent.StartTime)
        {
        var levellink = level;
        if (link != "-")
         levellink = "<a href='" + link + "' class=\"changeCity Green Bold\" cityid="+CityId+">"+level+"</a>";
        levellink += '<sup class=Red title="Require attention">!</sup>';
        levelUpgrading = createTooltip(levellink, '<nobr>'+sdate+'</nobr>', this._Parent.Intl.TT("finishedBuilding")+':' );
        }
       else
        {
        var counter = "<font id='mytimecounter' counter='"+Math.round(underConstructionTime)+"' class='time_counter'>___:___:___</font>";
        var levellink =level+"&raquo;"+(level+1);
        if (link != "-")
         levellink = "<a href='" + link + "' class=\"changeCity Green Bold\" cityid="+CityId+">"+level+"&raquo;"+(level+1)+"</a>";
        if ((level > 0) && (reportViewToSurvey(key, CityId) == '!'))
         {
         levellink += '<sup class=Red title="Require attention">!</sup>';
         }
        else
         {
         levellink += '&nbsp;';
         }
        levelUpgrading = createTooltip(levellink, '<nobr>'+sdate +' ('+ counter+')</nobr>', this._Parent.Intl.TT("currentlyBuilding")+':');
        }
       s += "<td level='"+level+"' view='"+key+"' position='"+position+"' class='"+firstStyle+" "+key+" "+currentBuildingStyle+"'>"+levelUpgrading+"</td>";
       }
      else
       {
       var levellink =level;
       if (level != "-")
        {
        levellink = "<a href='" + link + "' class=changeCity cityid="+CityId+">"+level+"</a>";
        
        if (reportViewToSurvey(key, CityId) == '!')
         {
         levellink += '<sup class=Red title="Require attention">!</sup>';
         }
        else
         {
         levellink += '&nbsp;';
         }
        }
       else
        {
        levellink += '&nbsp;';
        }
       s += "<td level='"+level+"' view='"+key+"' position='"+position+"' class='"+firstStyle+" "+key+" "+currentBuildingStyle+"'>"+levellink+"</td>";
       }
      buildingCount++;
      firstStyle = 'lfdash';
      }
     }
    else
     {
     s += "<td level='0' view='"+key+"' class='"+firstStyle+" "+key+"'>-&nbsp;</td>";
     buildingCount++;
     firstStyle = '';
     }

    if (buildingCount < buildingsCount[key])
     {
     for (var j = buildingCount; j < buildingsCount[key]; j++)
      {
      s += "<td level='0' view='"+key+"' class='"+firstStyle+" "+key+"'>-&nbsp;</td>";
      firstStyle = 'lfdash';
      }
     }

    lastTopic = orderedBuildings[key];
    }
   }
  
  if (buildsNum <= 1) s += "<td class='lf'></td><td></td><td></td><td></td><td></td><td></td>";
  
  s += "</tr>";
  
  if (odd == '') { odd = 'odd'; } else { odd = ''; }
  i++;
  }
 
 s += "</tbody>";
 
 s += "<tfoot></tfoot>";
 
 s += "</table>";
 
 return s;
 };
 
EmpireBoard.Renders.Resources_Table_Content = function()
 {
 var _self = this;
 
 var s = "";
 var Cities = this._Parent.DB.CurrentCities;
 
 s += "<table class='Overview Resources'>";
 
 function createLinkToFinanceNavyViews()
  {
  var rHTML = '';
   
  rHTML += '<a href="?view=merchantNavy" title="View merchant navy"><img align="absmiddle" src="skin/img/city/building_port.gif" /></a>';
  if (reportViewToSurvey('merchantNavy') == '!')
   {
   rHTML += '<sup class=Red title="Require attention">!</sup>';
   }
  else
   {
   rHTML += '&nbsp;';
   }
  
  rHTML += '<a href="?view=finances" title="View finances"><img align="absmiddle" src="skin/img/city/building_townhall.gif" /></a>';
  if (reportViewToSurvey('finances') == '!')
   {
   rHTML += '<sup class=Red title="Require attention">!</sup>';
   }
  else
   {
   rHTML += '&nbsp;';
   }
  
  return rHTML;
  }

 s += "<thead><tr>";
 s += "<th class='city_name' nowrap>"+this._Parent.Intl.TT("cityName")+"</th>"+
   "<th class='actions' nowrap>"+createLinkToFinanceNavyViews()+"</th>"+
   "<th colspan=3 class='lf population' nowrap>"+this._Parent.Intl.TT("Population")+"</th>"+
   "<th colspan=1 class='growth' nowrap>"+this._Parent.Intl.TT("Growth")+"</th>"+
   "<th colspan=1 class='lf research' nowrap>"+this._Parent.Intl.TT("Research")+"</th>"+
   "<th colspan=1 class='lf incomes' nowrap>"+this._Parent.Intl.TT("Incomes")+"</th>"+
   "<th colspan=2 class='lf wood'>"+this._Parent.Intl.TT("Wood")+"</th>"+
   "<th colspan=3 class='lf wine'>"+this._Parent.Intl.TT("Wine")+"</th>"+
   "<th colspan=2 class='lf marble'>"+this._Parent.Intl.TT("Marble")+"</th>"+
   "<th colspan=2 class='lf crystal'>"+this._Parent.Intl.TT("Crystal")+"</th>"+
   "<th colspan=2 class='lf sulfur'>"+this._Parent.Intl.TT("Sulfur")+"</th>";
 s += "</tr></thead>";
 
 var sumres = new Resource("");
 sumres.population  = 0;
 sumres.citizens   = 0;
 sumres.spacetotal  = 0;
 sumres.growth   = 0;
 sumres.Income   = 0;
 sumres.reservedGold  = '';
 sumres.Research   = 0;
 
 var sumProd = new Resource("");
 sumProd.wineUsage = 0;
 
 var sumArTr = new Resource("");

 function createIncome(prodPerHour, extraTooltip, classname)
  {
  if (classname == undefined) classname = '';
  if (""+prodPerHour == "NaN" || ""+prodPerHour == "" || ""+prodPerHour == "?" || prodPerHour == undefined || ""+prodPerHour == "???")
   {
   return "?";
   }
  else if (""+prodPerHour == "0")
   {
   return "0";
   }
  else
   {
   var tooltip = _self._Parent.Str.FormatBigNumber(Math.round(24 * prodPerHour), true)+" / "+_self._Parent.Ikariam.LocalizationStrings('day','timeunits','short');
   if ((extraTooltip != undefined) && (extraTooltip != ''))
    {
    tooltip += "<br>&nbsp;"+extraTooltip;
    }
   return createTooltip('<span class="'+classname+'">'+_self._Parent.Str.FormatBigNumber(Math.round(prodPerHour), true)+'</span>', tooltip);
   }
  }

 function createLinkToAgora(city_id)
  {
  var rHTML = '';
  
  if (_self._Parent.Ikariam.Is_Version_032x() == true)
   {
   var res = getCity(city_id);
   
   if (res.island_id != undefined)
    {
    rHTML += '<a href="?view=islandBoard&id='+res.island_id+'" title="View island agora"><img hspace="3" height="12" src="skin/board/schriftrolle_offen2.gif" align="absmiddle" /></a>';
    }
   }
   
  return rHTML;
  }

 function createLinkToMap(city_id)
  {
  var res = getCity(city_id);
  var rHTML = '';
  
  if (res.city_coord != undefined)
   {
   cCoord =  res.city_coord.split(":");
   rHTML += '<a href="?view=worldmap_iso&islandX='+_self._Parent.Str.To_Integer(cCoord[0],'')+'&islandY='+_self._Parent.Str.To_Integer(cCoord[1],'')+'" title="' + res.city_coord + ' View world map"><img align="absmiddle" src="skin/layout/icon-world.gif" /></a>'; 
   }
   
  if ((res.island_id != undefined) && (res.city_coord != undefined))
   {
   rHTML += '<a href="?view=island&id=' + res.island_id + '&selectCity='+city_id+'" title="' + res.city_coord + ' View island"><img align="absmiddle" src="skin/layout/icon-island.gif" /></a>'; 
   }
  else if (res.island_id != undefined)
   {
   rHTML += '<a href="?view=island&id=' + res.island_id + '&selectCity='+city_id+'" title="View island"><img align="absmiddle" src="skin/layout/icon-island.gif" /></a>'; 
   }
   
  return rHTML;
  }

 function createLinkToResourceCond(condition, text, island_id, city_id, city_index)
  {
  if (condition == true && island_id != undefined && island_id != "")
   {
   return createLink(text, "?view=resource&type=resource&id="+island_id, "class=changeCity cityid="+city_id);
   }
  return text;
  }

 function createLinkToTradegoodCond(condition, text, island_id, city_id, city_index)
  {
  if (condition == true && island_id != undefined && island_id != "")
   {
   return createLink(text, "?view=tradegood&type=tradegood&id="+island_id, "class=changeCity cityid="+city_id);
   }
  return text;
  }

 function createLinkToResources(city_id)
  {
  var res = getCity(city_id);
  var rHTML = '';
  if (res.island_id != undefined)
   {
   rHTML += '<a class="changeCity" cityid="'+city_id+'" href="?view=resource&type=resource&id=' + res.island_id + '" title="View island saw mill"><img height="12" align="absmiddle" src="skin/resources/icon_wood.gif" /></a>';
   rHTML += '&nbsp;';
   
   if (res.prodgood == 'wine')
    {
    rHTML += '<a class="changeCity" cityid="'+city_id+'" href="?view=tradegood&type=tradegood&id=' + res.island_id + '" title="View island vineyard"><img height="12" align="absmiddle" src="skin/resources/icon_wine.gif" /></a>';
    }
   else if (res.prodgood == 'marble')
    {
    rHTML += '<a class="changeCity" cityid="'+city_id+'" href="?view=tradegood&type=tradegood&id=' + res.island_id + '" title="View island quarry"><img height="12" align="absmiddle" src="skin/resources/icon_marble.gif" /></a>';
    }
   else if (res.prodgood == 'glass')
    {
    rHTML += '<a class="changeCity" cityid="'+city_id+'" href="?view=tradegood&type=tradegood&id=' + res.island_id + '" title="View island crystal mine"><img height="12" align="absmiddle" src="skin/resources/icon_glass.gif" /></a>';
    }
   else if (res.prodgood == 'sulfur')
    {
    rHTML += '<a class="changeCity" cityid="'+city_id+'" href="?view=tradegood&type=tradegood&id=' + res.island_id + '" title="View island sulphur pit"><img height="12" align="absmiddle" src="skin/resources/icon_sulfur.gif" /></a>';
    }
    
   rHTML += '&nbsp;';
   }
  return rHTML;
  }

 function createLinkToTransportGoods(city_id)
  {
  var rHTML = '';
  if (current_city_id == city_id)
   {
   rHTML += '<img class="Action" src="skin/actions/transport_disabled.gif" align="absmiddle" />';
   }
  else
   {
   rHTML += '<a view=transport href="?view=transport&destinationCityId='+city_id+'" title="Transports goods"><img class="Action" src="skin/actions/transport.gif" align="absmiddle" /></a>';
   }
  return rHTML;
  }

 function createProd(prodPerHour, extraTooltip)
  {
  if (prodPerHour == "-" || prodPerHour == "?")
   {
   return prodPerHour;
   }
  else if (""+prodPerHour == "NaN" || ""+prodPerHour == "" || ""+prodPerHour == "0" || prodPerHour == undefined || ""+prodPerHour == "???")
   {
   return "";
   }
  else
   {
   var tooltip = _self._Parent.Str.FormatBigNumber(Math.round(24 * prodPerHour), true)+" / "+_self._Parent.Ikariam.LocalizationStrings('day','timeunits','short');
   if (extraTooltip != undefined)
    {
    tooltip += ", "+extraTooltip;
    }
   return createTooltip(_self._Parent.Str.FormatBigNumber(Math.round(prodPerHour), true), tooltip);
   }
  }

 function createResCounter(startTime, startAmount, factPerHour, showTooltip, maxAmount, tradeAmount, secureAmount, arrAmount)
  {
  if (tradeAmount == undefined) tradeAmount = 0;
  if (arrAmount == undefined) arrAmount = 0;
  if ((maxAmount == undefined) || (maxAmount == '-'))
   {
   maxAmount = '-';
   }
  else
   {
   maxAmount = maxAmount - tradeAmount;
   }
  var currAmount = startAmount;
  var tooltip = "";
  var res;
  
  if ((startAmount == undefined) || (startAmount+"" == "NaN"))
   {
   res = '?';
   }
  else if ((factPerHour != undefined) && (factPerHour+"" != "NaN") && (factPerHour != 0))
   {
   var counterClass = '';
   var intfactPerHour = Math.round(factPerHour);
   var dailyFact = Math.round(24 * factPerHour);
   if (startTime != undefined)
    {
    currAmount = getCurrentResourceAmount(_self._Parent.StartTime, startTime, startAmount, intfactPerHour);
    if (intfactPerHour > 0)
     {
     counterClass = 'Bold';
     }
    else if (intfactPerHour < 0)
     {
     if (currAmount+(6*intfactPerHour) <= 0)
      {
      counterClass = 'Red';
      }
     else if (currAmount+(24*intfactPerHour) <= 0)
      {
      counterClass = 'DarkRed';
      }
     }
    res = "<font id='myresourcecounter' counter='"+startTime+","+startAmount+","+intfactPerHour+","+maxAmount+"' class='"+counterClass+"'>"+_self._Parent.Str.FormatBigNumber(currAmount)+"</font>";
    }
   
   if (showTooltip == true) 
    {
       tooltip = _self._Parent.Str.FormatBigNumber(intfactPerHour, true)+" / "+_self._Parent.Ikariam.LocalizationStrings('hour','timeunits','short')+"<br> "+_self._Parent.Str.FormatBigNumber(dailyFact, true)+" / "+_self._Parent.Ikariam.LocalizationStrings('day','timeunits','short');
    if (intfactPerHour < 0)
     tooltip += "<br>&nbsp;" + _self._Parent.Str.FormatRemainingTime(-1 * (currAmount+arrAmount) / intfactPerHour * 60 * 60 * 1000) + " to empty";
    }
   }
  else
   {
   res = _self._Parent.Str.FormatBigNumber(currAmount);
   }
   
  // Safety goods ?
  if ((secureAmount > 0) && (secureAmount >= (currAmount+tradeAmount)))
   {
   res = '<img src="skin/layout/icon-wall.gif" class="Safe" title="Safety resources"/> '+res;
   }
   
  if (tooltip != '') res = createTooltip(res, tooltip);
  return res + "&nbsp;";
  }
 
 function createResearch(prodPerHour, extraTooltip)
  {
  if (prodPerHour == "-" || prodPerHour == "?")
   {
   return prodPerHour;
   }
  else if (""+prodPerHour == "0")
   {
   return '+0';
   }
  else if (""+prodPerHour == "NaN" || ""+prodPerHour == "" || prodPerHour == undefined || ""+prodPerHour == "???")
   {
   return "";
   }
  else
   {
   var tooltip = _self._Parent.Str.FormatBigNumber(Math.round(24 * prodPerHour), true)+" / "+_self._Parent.Ikariam.LocalizationStrings('day','timeunits','short');
   if (extraTooltip != undefined)
    {
    tooltip += ", "+extraTooltip;
    }
   return createTooltip(_self._Parent.Str.FormatBigNumber(Math.round(prodPerHour), true), tooltip);
   }
  }

 function getArrivingGoodsSum(city_id, resName)
  {
  var sum = 0;
  var city = getCity(city_id);
  var rows = getArrValue(config.arrivinggoods, city_id, []);
  var key;
  for (key in rows)
   {
   var row = rows[key];
   var res = row["res"];
   var a = getArrValue(res, resName, 0);
   var arrivetime = parseInt(getArrValue(row, "arrivetime", ""));
   if ((a > 0) && (arrivetime > city.prodtime)) sum += a;
   }
  return sum;
  }
 
 function getArrivingGoods(city_id, resName, tradinggoods, resAmount, ArrivingGoodsSum)
  {
  var sum = 0;
  var found = false;
  if (ArrivingGoodsSum == undefined)
   ArrivingGoodsSum = getArrivingGoodsSum(city_id, resName);
  if (ArrivingGoodsSum > 0)
   {
   sum += ArrivingGoodsSum;
   found = true;
   }

  if ((tradinggoods != undefined) && (parseInt(tradinggoods) > 0))
   {
   sum += parseInt(tradinggoods);
   }

  var s = "<font class='More'>-&nbsp;</font>";
  if (found == true)
   {
   s = "<font class='More MoreGoods Green'>"+_self._Parent.Str.FormatBigNumber(sum, true);
   if (getDeliveredGoodsTransports(city_id, resName) > 0)
    {
    s += "<sup>*</sup>";
    }
   else s += "&nbsp;";
   s += "</font>";
   }
  else if (sum > 0)
   {
   s = "<font class='More MoreGoods'>"+_self._Parent.Str.FormatBigNumber(sum, true)+"&nbsp;</font>";
   }
  return s;
  }

 function createReservedGold(sum)
  {
  var output = '';
  if (sum == '?')
   {
   output = '<font class="More">?</font>';
   }
  else if (sum === 0)
   {
   output = '<font class="More">-</font>';
   }
  else if ((sum != undefined) && (sum != ''))
   {
   output = '<font class="More" title="Reserved gold">'+_self._Parent.Str.FormatBigNumber(sum)+'</font>';
   }
  return output;
  }
  
 function createSimpleProd(prodPerHour)
  {
  if (""+prodPerHour == "NaN" || ""+prodPerHour == "" || ""+prodPerHour == "0" || prodPerHour == undefined || ""+prodPerHour == "???")
   {
   return "";
   }
  return _self._Parent.Str.FormatBigNumber(Math.round(prodPerHour), true);
  }

 function createTransports(cityID)
  {
  var res = "<font class='More'></font>";
  var numTransports = 0;
  if (config["transports"] == undefined)
   {
   
   }
  else if (config["transports"][cityID] != undefined)
   {
   for (key in config["transports"][cityID])
    {
    if (config["transports"][cityID][key].endTime >= _self._Parent.StartTime) numTransports++;
    }
    
   if (numTransports > 0) res = "<font class='More'>"+numTransports+" transport(s) on way</font>";
   }
   
  return res;
  }

 function createResProgressBar(startTime, startAmount, factPerHour, maxCapacity, secureCapacity)
  {
  var res = '';
  if ((_self._Parent.DB.Options.Prefs.PROGRESS_BAR_MODE != "off") && (maxCapacity > 0) && (startTime != undefined))
   {
   var curres = getCurrentResourceAmount(new Date().getTime(), startTime, startAmount, factPerHour);
   var perc = Math.min(100, Math.round(curres / maxCapacity * 100.0));
   var remaining = "";
   var remhour = 100000000;
   if (curres >= maxCapacity)
    {
    // no more
    remhour = 0;
    }
   else if (factPerHour > 0)
    {
    remhour = (maxCapacity - curres) / factPerHour;
    remaining = "<br>"+_self._Parent.Str.FormatRemainingTime(remhour*60*60*1000)+" to full";
    }
   else if (factPerHour < 0)
    {
    remaining = "<br>"+_self._Parent.Str.FormatRemainingTime((curres / -factPerHour)*60*60*1000) + " to empty";
    }
   var cl = "Normal";
   var vperc = perc;
   if ((curres > 0) && (vperc < 4)) vperc = 4;
   if ((_self._Parent.DB.Options.Prefs.PROGRESS_BAR_MODE == "time") && (factPerHour != 0))
    {
    if (remhour <= 1) 
     {
     cl = "Full";
     } 
    else if (remhour < 24)
     {
     cl = "AlmostFull";
     }
    else if (remhour < 72)
     {
     cl = "Warning";
     }
    }
   else
    {
    if (perc >= 99)
     {
     cl = "Full";
     }
    else if (perc >= 90)
     {
     cl = "AlmostFull";
     }
    else if (perc >= 80)
     {
     cl = "Warning";
     }
    } 
   res +=  "<table class='myPercent' "+createTooltipAttribute(_self._Parent.Str.FormatBigNumber(maxCapacity) + " total capacity<br>"+_self._Parent.Str.FormatBigNumber(secureCapacity)+" safety capacity<br>" + perc+"% full" + remaining)+">"+
   "<tr>"+
   "<td width='"+vperc+"%' class='"+cl+"'></td>"+
   "<td width='"+(100-vperc)+"%'></td>"+
   "</tr>"+
   "</table>";
   }
  else if (_self._Parent.DB.Options.Prefs.PROGRESS_BAR_MODE != "off")
   {
   res +=  "<table class='myPercent'>"+
   "<tr>"+
   "<td></td>"+
   "</tr>"+
   "</table>";
   }
  return res;
  }

 s += "<tbody>";

 var CityId;
 var i = 0;
 var odd = '';
 for (CityId in Cities)
  {
  if (Cities[CityId].own != true) continue;
  var city = getCity(CityId);
  
  if (getBuildingLevel(CityId, "branchOffice", "-") != '-')
   {
   if (city.tradewood == undefined) city.tradewood = 0;
   if (city.tradewine == undefined) city.tradewine = 0;
   if (city.trademarble == undefined) city.trademarble = 0;
   if (city.tradeglass == undefined) city.tradeglass = 0;
   if (city.tradesulfur == undefined) city.tradesulfur = 0;
   }
  else
   {
   city.tradewood = 0;
   city.tradewine = 0;
   city.trademarble = 0;
   city.tradeglass = 0;
   city.tradesulfur = 0;
   }
  
  // Try to estimate wine usage
  var wineUsage;
  var cellarLevel = getBuildingLevel(CityId, "vineyard", "-");
  if (city.wineUsageId != undefined)
   {
   wineUsage = tavernWineUsage[city.wineUsageId];
   if (cellarLevel != '-') 
    {
    wineSave = wineUsage * cellarLevel;
    wineSave = Math.round(wineSave / 100);
    wineUsage = wineUsage - wineSave;
    }
   }
  else if (city.wineUsage != undefined)
   {
   wineUsage = city.wineUsage;
   } 
  else 
   {
   // estimate max wine usage
   var tavernLevel = getBuildingLevel(CityId, "tavern", "-");
   wineUsage = (tavernLevel != '-' ? tavernWineUsage[tavernLevel] : 0);
   if (cellarLevel != '-')
    {
    wineSave = wineUsage * cellarLevel;
    wineSave = Math.round(wineSave / 100);
    wineUsage = wineUsage - wineSave;
    }
   }
  // Wine usage tooltip
  var wineUsageHtml = '-';
  if (wineUsage > 0)
   {
   wineUsageHtml = createSimpleProd(-1 * wineUsage);
   }
  
  // Estimate current amount of each resources
  var curres = new Resource("");
  curres.wood   = getCurrentResourceAmount(this._Parent.StartTime, city.prodtime, city.wood, city.prodwood);
  curres.wine   = getCurrentResourceAmount(this._Parent.StartTime, city.prodtime, city.wine, city.prodwine - wineUsage);
  curres.marble  = getCurrentResourceAmount(this._Parent.StartTime, city.prodtime, city.marble, city.prodmarble);
  curres.glass  = getCurrentResourceAmount(this._Parent.StartTime, city.prodtime, city.glass, city.prodglass);
  curres.sulfur  = getCurrentResourceAmount(this._Parent.StartTime, city.prodtime, city.sulfur, city.prodsulfur);

  sumres.wood   += curres.wood;
  sumres.wine   += curres.wine;
  sumres.marble  += curres.marble;
  sumres.glass  += curres.glass;
  sumres.sulfur  += curres.sulfur;

  sumProd.wood   += city.prodwood;
  sumProd.wine   += city.prodwine;
  sumProd.wineUsage  += wineUsage;
  sumProd.marble   += city.prodmarble;
  sumProd.glass   += city.prodglass;
  sumProd.sulfur   += city.prodsulfur;
  
  // Resources which will arrive
  var arrres = new Resource('');
  arrres.wood   = getArrivingGoodsSum(CityId, 'wood');
  arrres.wine   = getArrivingGoodsSum(CityId, 'wine');
  arrres.marble  = getArrivingGoodsSum(CityId, 'marble');
  arrres.glass  = getArrivingGoodsSum(CityId, 'glass');
  arrres.sulfur  = getArrivingGoodsSum(CityId, 'sulfur');

  sumArTr.wood  += city.tradewood + arrres.wood;
  sumArTr.wine  += city.tradewine + arrres.wine;
  sumArTr.marble  += city.trademarble + arrres.marble;
  sumArTr.glass  += city.tradeglass + arrres.glass;
  sumArTr.sulfur  += city.tradesulfur + arrres.sulfur;
  
  // City income
  var Income = getArrValue(city.buildings["townHall"],"incomegold","?");
  if (Income != "?")
   {
   sumres.Income += Income;
   }
  
  // Gold in trading post
  var reservedGold = '';
  if (city.buildings["branchOffice"] != undefined)
   {
   if (city.buildings["branchOffice"].reservedGold == undefined)
    {
    reservedGold = '?';
    }
   else
    {
    reservedGold = city.buildings["branchOffice"].reservedGold;
    if (reservedGold > 0)
     {
     if (sumres.reservedGold == '')
      {
      sumres.reservedGold = reservedGold;
      }
     else
      {
      sumres.reservedGold += reservedGold;
      }
     }
    }
   }
   
  // Research point
  var Research = '-';
  if (getBuildingLevel(CityId, "academy", 0) > 0)
   {
   Research = getArrValue(city.buildings["academy"],"Research","?");
   
   if (Research != '?')
    {
    sumres.Research += Research;
    }
   }
  
  var spacetotal   = '?';
  var townHallLevel  = getBuildingLevel(CityId, "townHall", "?", 0);
  if (townHallLevel != '?')
   spacetotal = townHallSpaces[townHallLevel];
  var bonusspace   = getArrValue(city.buildings["townHall"], "bonusspace", "?");

  var workers    = '?';
  var population   = getArrValue(city.buildings["townHall"], "population", 0);
  var citizens   = getArrValue(city.buildings["townHall"], "citizens", '?');
  if (citizens != '?')
   workers = population - citizens;
  
  // Estimate current population and growth
  var growth    = 0;
  var happiness   = getArrValue(city.buildings["townHall"], "happiness", "?");
  if ((happiness != '?') && (spacetotal != '?') && (bonusspace != '?'))
   {
   population = getEstimatedPopulation(population, city.prodtime, this._Parent.StartTime, happiness - population);
   if (parseInt(population) > parseInt(spacetotal) + parseInt(bonusspace))
    {
    population = parseInt(spacetotal) + parseInt(bonusspace);
    }
   happiness -= population;
   
   if (happiness != 0)
    growth = (0.02 * happiness) + 0.01;
   }
  else
   {
   growth = getArrValue(city.buildings["townHall"], "growth", "?");
   }
  sumres.population += population;
  
  // Current citizens
  if (workers != '?')
   {
   citizens = population - workers;
   if (sumres.citizens != '?')
    {
    sumres.citizens += citizens;
    }
   }
  else
   {
   citizens = '?';
   sumres.citizens = '?';
   }
  
  // Estimate growth remaining time
  var growthRemainingHours = '';
  if (happiness != "?" && happiness > 0 && bonusspace != "?" && growth >= 0.20)
   {
   growthRemainingHours = getGrowthRemainingHours(population, parseInt(spacetotal) + parseInt(bonusspace), this._Parent.StartTime, happiness);
   }
  
  // Global growth
  if ((growth != '?') && (sumres.growth != '?'))
   {
   if (parseInt(population) < parseInt(spacetotal) + parseInt(bonusspace))
    sumres.growth += growth;
   }
  else
   {
   sumres.growth = '?';
   }
  
  // Is current city ?
  var trclass = "";
  if (parseInt(current_city_id) == parseInt(CityId))
   {
   trclass = "current";
   }

  var townHallStyle = "";
  var growthStyle = "";
  if (parseInt(population) >= parseInt(spacetotal) + parseInt(bonusspace))
   {
   // Townhall is full
   growthRemainingHours = '';
   if (growth >= 1.20) 
    {
    townHallStyle = " DarkRed";
    }
   else if (growth >= 0.20) 
    {
    townHallStyle = " Brown";
    }
   else
    {
    townHallStyle = " Bold";
    }
   }
  else if (growth >= 0.20)
   {
   growthStyle = " Green";
   }
  else if (growth >= 0)
   {
   growthStyle = "";
   }
  else if (growth <= -1)
   {
   growthStyle = " Red";
   }
  else if (growth <= -0.20)
   {
   growthStyle = " DarkRed";
   }
  
  // Global townhall capacity
  if (bonusspace != "?")
   {
   if (sumres.spacetotal != '?')
    sumres.spacetotal += parseInt(spacetotal) + parseInt(bonusspace);
   spacetotal = this._Parent.Str.FormatBigNumber(parseInt(spacetotal) + parseInt(bonusspace));

   }
  else
   {
   sumres.spacetotal = '?';
   spacetotal = this._Parent.Str.FormatBigNumber(spacetotal) + " + ?";
   }
  
  // Warehouse safe capacity bonus by premium option
  var savecapacityBonus = 0;
  if (config["premium"] != undefined)
   {
   if ((config["premium"].savecapacityBonus != undefined) && (config["premium"].savecapacityBonus > this._Parent.StartTime))
    {
    savecapacityBonus = 100;
    }
   }
  
  // Warehouse storage capacity bonus by premium option
  var storagecapacityBonus = 0;
  if (config["premium"] != undefined)
   {
   if ((config["premium"].storagecapacityBonus != undefined) && (config["premium"].storagecapacityBonus > this._Parent.StartTime))
    {
    storagecapacityBonus = 100;
    }
   }
  
  // Warehouse max capacity
  var maxcwood   = 0;
  var maxcother   = 0;
  var maxsafewood   = 0;
  var maxsafeother  = 0;
  if (this._Parent.Ikariam.Is_Version_034x() == true)
   {
   var WarehousesLevels = [];
   var WarehousesLevel = 0;
   if ((city.buildings['warehouse'] != undefined) && (city.buildings['warehouse'].levels != undefined))
    {
    var p;
    for (p in city.buildings['warehouse'].levels)
     {
     var WarehouseLevel = getBuildingLevel(CityId, 'warehouse', city.buildings['warehouse'].levels[p], p);
     WarehousesLevel += WarehouseLevel;
     WarehousesLevels.push(WarehouseLevel);
     }
    }
   else
    {
    // While build first warehouse
    WarehousesLevel  = getBuildingLevel(CityId,'warehouse', 0, -1);
    WarehousesLevels.push(WarehousesLevel);
    }
    
   var DumpLevel = getBuildingLevel(CityId,'dump', 0, -1);
   
   maxcwood   = this._Parent.Ikariam.Resource_Capacity('wood',WarehousesLevel,DumpLevel,storagecapacityBonus);
   maxcother   = maxcwood;
   maxsafewood   = this._Parent.Ikariam.Resource_SafeCapacity('wood',WarehousesLevels,savecapacityBonus);
   maxsafeother  = maxsafewood;
   }
  else
   {
   // Soon deprecated
   var WarehousesLevel  = getBuildingLevel(CityId,'warehouse', 0, -1);
   
   maxcwood   = this._Parent.Ikariam.Resource_Capacity('wood',WarehousesLevel,0,storagecapacityBonus);
   maxcother   = this._Parent.Ikariam.Resource_Capacity('wine',WarehousesLevel,0,storagecapacityBonus);
   maxsafewood   = this._Parent.Ikariam.Resource_SafeCapacity('wood',WarehousesLevel,savecapacityBonus);
   maxsafeother  = this._Parent.Ikariam.Resource_SafeCapacity('wine',WarehousesLevel,savecapacityBonus);
   }

  var cityLink = '';
  if (reportViewToSurvey('',CityId) == '!')
   {
   cityLink = createLinkToChangeCity(Cities[CityId].name, CityId, i, reportViewToSurvey('',CityId),'Red', 'Require attention');
   }
  else
   {
   cityLink = createLinkToChangeCity(Cities[CityId].name, CityId, i , city.actions, 'Green', 'Available action points');
   }
  
  s += "<tr class='"+odd+" "+trclass+"' cityid='"+CityId+"' islandid='"+city.island_id+"' coord='"+city.city_coord+"' tradegood='"+city.prodgood+"'>";
  
  s += "<td class='city_name' nowrap>"+cityLink+createTransports(CityId)+"</td>"+
    "<td class='actions' nowrap>"+createLinkToMap(CityId)+createLinkToAgora(CityId)+"<br />"+createLinkToResources(CityId)+createLinkToTransportGoods(CityId)+"</td>"+
    "<td class='lf'>"+
     "<span title='Citizens'>"+(population > 0 ? this._Parent.Str.FormatBigNumber(citizens) : '?')+"</span>"+
     "&nbsp;("+
    "</td>"+
    "<td class='nolf'>"+
     "<span title='Overall inhabitants' class='inhabitant"+townHallStyle+"'>"+(population > 0 ? this._Parent.Str.FormatBigNumber(population) : '?')+"</span>)"+
     "&nbsp;/</td>"+
    "<td class='nolf' title='Housing space'>"+spacetotal+"</td>"+
    "<td class='"+growthStyle+"'>"+(growth != '?' ? '<img src="'+this._Parent.Ikariam.Get_Happiness_ImgSrc(growth)+'" align=left height=18 hspace=2 vspace=0 title="Total satisfaction: '+happiness+'">' : '')+createTooltip(this._Parent.Str.FormatFloatNumber(growth,2,true), growthRemainingHours)+"</td>"+
    "<td class='lf'>"+createResearch(Research)+"</td>"+
    "<td class='lf'>"+
     createIncome(Income)+
     createReservedGold(reservedGold)+
    "</td>"+
    "<td class='lf' resource='wood'>"+
     createLinkToResourceCond(true, createResCounter(city.prodtime, city.wood, city.prodwood, false, maxcwood, city.tradewood, maxsafewood), city.island_id, CityId, i)+
     getArrivingGoods(CityId, "wood", city.tradewood, curres.wood, arrres.wood)+
     createResProgressBar(city.prodtime, city.wood + arrres.wood, city.prodwood, maxcwood - city.tradewood, maxsafewood)+
    "</td>"+
    "<td class='lfdash'>"+createProd(city.prodwood)+"</td>"+
    "<td class='lf' resource='wine'>"+
     createLinkToTradegoodCond((city.prodwine > 0) || (city.prodgood == 'wine'), createResCounter(city.prodtime, city.wine, city.prodwine - wineUsage, true, maxcother, city.tradewine, maxsafeother, arrres.wine), city.island_id, CityId, i)+
     getArrivingGoods(CityId, "wine", city.tradewine, curres.wine, arrres.wine)+
     createResProgressBar(city.prodtime, city.wine + arrres.wine, city.prodwine - wineUsage, maxcother - city.tradewine, maxsafeother)+
    "</td>"+
    "<td class='lfdash'>"+createSimpleProd(city.prodwine)+"</td>"+
    "<td class='lfdash'>"+wineUsageHtml+"</td>"+
    "<td class='lf' resource='marble'>"+
     createLinkToTradegoodCond((city.prodmarble > 0) || (city.prodgood == 'marble'), createResCounter(city.prodtime, city.marble, city.prodmarble, false, maxcother, city.trademarble, maxsafeother), city.island_id, CityId, i)+
     getArrivingGoods(CityId, "marble", city.trademarble, curres.marble, arrres.marble)+
     createResProgressBar(city.prodtime, city.marble + arrres.marble, city.prodmarble, maxcother - city.trademarble, maxsafeother)+
    "</td>"+
    "<td class='lfdash'>"+createProd(city.prodmarble)+"</td>"+
    "<td class='lf' resource='glass'>"+
     createLinkToTradegoodCond((city.prodglass > 0) || (city.prodgood == 'glass'), createResCounter(city.prodtime, city.glass, city.prodglass, false, maxcother, city.tradeglass, maxsafeother), city.island_id, CityId, i)+
     getArrivingGoods(CityId, "glass", city.tradeglass, curres.glass, arrres.glass)+
     createResProgressBar(city.prodtime, city.glass + arrres.glass, city.prodglass, maxcother - city.tradeglass, maxsafeother)+
    "</td>"+
    "<td class='lfdash'>"+createProd(city.prodglass)+"</td>"+
    "<td class='lf' resource='sulfur'>"+
     createLinkToTradegoodCond((city.prodsulfur > 0) || (city.prodgood == 'sulfur'), createResCounter(city.prodtime, city.sulfur, city.prodsulfur, false, maxcother, city.tradesulfur, maxsafeother), city.island_id, CityId, i)+
     getArrivingGoods(CityId, "sulfur", city.tradesulfur, curres.sulfur, arrres.sulfur)+
     createResProgressBar(city.prodtime, city.sulfur + arrres.sulfur, city.prodsulfur, maxcother - city.tradesulfur, maxsafeother)+
    "</td>"+
    "<td class='lfdash'>"+createProd(city.prodsulfur)+"</td>";
  s += "</tr>";
  
  i++;
  if (odd == '') { odd = 'odd'; } else { odd = ''; }
  }
 
 s += "</tbody>";
 
 // Gold usage remaining time
 var goldRemainingHours = '';
 var goldStyle = '';
 if (sumres.Income < 0) 
  {
  var RemainingHours = -1 * config.gold / sumres.Income;
  if (RemainingHours <= 6)
   {
   goldStyle = 'Red';
   }
  else if (RemainingHours <= 72)
   {
   goldStyle = 'DarkRed';
   }
  goldRemainingHours = _self._Parent.Str.FormatRemainingTime(RemainingHours*60*60*1000)+" to expense";
  }
 
 function createMoreGoods(sum)
  {
  var output = '';
  if (sum > 0) 
   {
   output = '<font class="More">'+_self._Parent.Str.FormatBigNumber(sum, true)+'&nbsp;</font>';
   }
   return output;
  }
  
 s += "<tfoot class='Summary'><tr>";
 s += "<td class='sigma' nowrap colspan=2><img vspace=2 hspace=5 src='skin/layout/sigma.gif'></td>"+
   "<td class='lf'>"+
   "<span title='Citizens'>"+this._Parent.Str.FormatBigNumber(sumres.citizens)+'</span>'+
   "&nbsp;("+
   "</td>"+
   "<td class='nolf'>"+
   "<span title='Overall inhabitants'>"+this._Parent.Str.FormatBigNumber(sumres.population)+"</span>)"+
   "&nbsp;/</td>"+
   "<td class='nolf' title='Housing space'>"+this._Parent.Str.FormatBigNumber(sumres.spacetotal)+"</td>"+
   "<td>"+this._Parent.Str.FormatFloatNumber(sumres.growth,2,true)+"</td>"+
   "<td class='lf'>"+createResearch(sumres.Research)+"</td>"+
   "<td class='lf'>"+
   createIncome(sumres.Income, goldRemainingHours, goldStyle)+
   createReservedGold(sumres.reservedGold)+
   "</td>"+
   "<td class='lf'>"+
       createResCounter(this._Parent.StartTime, sumres.wood, sumProd.wood)+
       createMoreGoods(sumArTr.wood)+
       "</td>"+
   "<td class='lfdash'>"+createProd(sumProd.wood)+"</td>"+
   "<td class='lf'>"+
       createResCounter(this._Parent.StartTime, sumres.wine, sumProd.wine - sumProd.wineUsage, true)+
       createMoreGoods(sumArTr.wine)+
       "</td>"+
   "<td class='lfdash'>"+createSimpleProd(sumProd.wine)+"</td>"+
   "<td class='lfdash'>"+createSimpleProd(-1 * sumProd.wineUsage)+"</td>"+
   "<td class='lf'>"+
       createResCounter(this._Parent.StartTime, sumres.marble, sumProd.marble)+
       createMoreGoods(sumArTr.marble)+
       "</td>"+
   "<td class='lfdash'>"+createProd(sumProd.marble)+"</td>"+
   "<td class='lf'>"+
       createResCounter(this._Parent.StartTime, sumres.glass, sumProd.glass)+
       createMoreGoods(sumArTr.glass)+
       "</td>"+
   "<td class='lfdash'>"+createProd(sumProd.glass)+"</td>"+
   "<td class='lf'>"+
       createResCounter(this._Parent.StartTime, sumres.sulfur, sumProd.sulfur)+
       createMoreGoods(sumArTr.sulfur)+
       "</td>"+
   "<td class='lfdash'>"+createProd(sumProd.sulfur)+"</td>";
 s += "</tr></tfoot>";
 
 s += "</table>";
 
 return s;
 };
 
EmpireBoard.Renders.ArmyFleet_Table_Content = function()
 {
 var _self = this;
 
 var s = "";
 var Cities = this._Parent.DB.CurrentCities;
 
 var FleetUpkeepBonus = 0;
 if (config["research"].FleetUpkeepBonus != undefined)
  FleetUpkeepBonus = config["research"].FleetUpkeepBonus;
 
 var ArmyUpkeepBonus = 0;
 if (config["research"].ArmyUpkeepBonus != undefined) 
  ArmyUpkeepBonus = config["research"].ArmyUpkeepBonus;
 
 function applyUpkeepBonus(value, bonus)
  {
  if ((value == '-') || (value == '?') || (value == 0) || (bonus == 0))
   {
   return value;
   }
  else
   {
   return (value - (value/100*bonus));
   }
  }
 
 var orderedUnits = this._Parent.Ikariam.UnitsList();
 
 function isArmy(key)
  {
  if (_self._Parent.Ikariam.Get_UnitGender(key) == 'army')
   return true;
  else
   return false;
  }
 
 function isFleet(key)
  {
  if (_self._Parent.Ikariam.Get_UnitGender(key) == 'fleet')
   return true;
  else
   return false;
  }
 
 var usedIndexes = {};
 var usedIndexesCount = 0;
 if (config["unitnames"] != undefined)
  {
  var CityId;
  for (CityId in Cities)
   {
   if (Cities[CityId].own != true) continue;
   var city = getCity(CityId);
   var key;
   for (key in orderedUnits)
    {
    var ukey = 'unit '+key;
    if (parseInt(getArrValue(getArrValue(city.units, ukey), "count", 0)) > 0)
     {
     usedIndexes[key] = 1;
     usedIndexesCount++;
     }
    else if (parseInt(getArrValue(getArrValue(city.units, ukey), "construction", 0)) > 0)
     {
     usedIndexes[key] = 1;
     usedIndexesCount++;
     }
    }
   }
  }
 
 s += "<thead><tr><th class='city_name' nowrap>"+this._Parent.Intl.TT("cityName")+"</th>";
 s += "<th class='actions' nowrap>"+this._Parent.Renders.ArmyFleet_HeaderIcons(current_city_id)+"</th>";
 if (usedIndexesCount > 0)
  {
  var firstStyle = "";
  var lastTopic = '';
  var key;
  for (key in orderedUnits)
   {
   var ukey = 'unit '+key;
   var name = this._Parent.Intl.TT(ukey,'army_units');
   if (usedIndexes[key] == 1) 
    {
    if (lastTopic != orderedUnits[key]) { firstStyle = "lf"; } else { firstStyle = ""; }
    
    s += "<th unit='"+key+"' class='"+firstStyle+" unit_name "+key+"' nowrap "+createTooltipAttribute(name)+">"+name+"</th>";
    firstStyle = "";
    
    lastTopic = orderedUnits[key];
    }
   }
  }
 else s += "<th class='lf'></th><th></th><th></th><th></th><th></th><th></th><th></th>";
 s += "<th class='upkeep lf' nowrap title='"+this._Parent.Intl.TT("Upkeep")+"'>"+this._Parent.Intl.TT("Upkeep")+"</th>";
 s += "</tr></thead>";
 
 function createAttacks(cityID)
  {
  var res = "<font class='More Red'></font>";
  var numMovements = 0;
  if (config["attacks"] == undefined)
   {
   
   }
  else if (config["attacks"][cityID] != undefined)
   {
   for (key in config["attacks"][cityID])
    {
    if (config["attacks"][cityID][key].endTime >= _self._Parent.StartTime)
     numMovements++;
    }
    
   if (numMovements > 0)
    res = "<font class='More Attacks Red'>under "+numMovements+" attack(s)</font>";
   }
   
  return res;
  }

 function createLinkToArmyView(city_id)
  {
  var rHTML = '';
  rHTML += '<a href="?view=cityMilitary-army&id='+city_id+'" class="changeCity" cityid="'+city_id+'" title="View army overview"><img align="absmiddle" src="skin/img/city/building_barracks.gif" /></a>';
  if (reportViewToSurvey('cityMilitary-army', city_id) == '!')
   {
   rHTML += '<sup class=Red title="Require attention">!</sup>';
   }
  else
   {
   rHTML += '&nbsp;';
   }
  return rHTML;
  }
 
 function createLinkToFleetView(city_id)
  {
  var rHTML = '';
  rHTML += '<a href="?view=cityMilitary-fleet&id='+city_id+'" class="changeCity" cityid="'+city_id+'" title="View fleet overview"><img align="absmiddle" src="skin/img/city/building_shipyard.gif" /></a>';
  if (reportViewToSurvey('cityMilitary-fleet', city_id) == '!')
   {
   rHTML += '<sup class=Red title="Require attention">!</sup>';
   }
  else
   {
   rHTML += '&nbsp;';
   }
  return rHTML;
  }
  
 function createLinkToDeployArmy(city_id)
  {
  var rHTML = '';
  if (current_city_id == city_id)
   {
   rHTML += '<img class="Action" src="skin/actions/move_army_disabled.gif" align="absmiddle" />';
   }
  else
   {
   rHTML += '<a view=deployment deploymenttype=army href="?view=deployment&deploymentType=army&destinationCityId='+city_id+'" title="Deploy troops"><img class="Action" src="skin/actions/move_army.gif" align="absmiddle" /></a>';
   }
  return rHTML;
  }

 function createLinkToDeployFleet(city_id)
  {
  var rHTML = '';
  if (current_city_id == city_id)
   {
   rHTML += '<img class="Action" src="skin/actions/move_fleet_disabled.gif" align="absmiddle" />';
   }
  else
   {
   rHTML += '<a view=deployment deploymenttype=fleet href="?view=deployment&deploymentType=fleet&destinationCityId='+city_id+'" title="Station fleets"><img class="Action" src="skin/actions/move_fleet.gif" align="absmiddle" /></a>';
   }
  return rHTML;
  }

 function createMovements(cityID)
  {
  var res = "<font class='More'></font>";
  var numMovements = 0;
  if (config["movements"] == undefined)
   {
   
   }
  else if (config["movements"][cityID] != undefined)
   {
   var key;
   for (key in config["movements"][cityID])
    {
    if (config["movements"][cityID][key].endTime >= _self._Parent.StartTime) numMovements++;
    }
    
   if (numMovements > 0) res = "<font class='More Movements'>"+numMovements+" movement(s) on way</font>";
   }
  return res;
  }

 var sum = [];
 var sumConstruction = [];
 var sumUpkeep = 0;
 var sumConstructionUpkeep = 0;
 s += "<tbody class='ownCities'>";
 var i = 0;
 var odd = '';
 var CityId;
 for (CityId in Cities)
  {
  if (Cities[CityId].own != true) continue;
  var city = getCity(CityId);
  var trclass = (parseInt(current_city_id) == parseInt(CityId)) ? "current" : "";
  
  s += "<tr class='"+odd+" "+trclass+"' cityid='"+CityId+"' islandid='"+city.island_id+"' coord='"+city.city_coord+"'>";
  
  s += "<td class='city_name' nowrap>"+
          createLinkToChangeCity(Cities[CityId].name, CityId, i, city.actions, 'Green', 'Available action points')+
          createMovements(CityId)+
          createAttacks(CityId)+
          "</td>";
  s += "<td class='actions' nowrap>"+createLinkToArmyView(CityId)+createLinkToDeployArmy(CityId)+"<br />"+createLinkToFleetView(CityId)+createLinkToDeployFleet(CityId)+"</td>";
  
  var cityUpkeep = 0;
  var cityConstructionUpkeep = 0;
  if (usedIndexesCount > 0)
   {
   var firstStyle = "";
   var lastTopic = '';
   for (key in orderedUnits)
    {
    var ukey = 'unit '+key;
    if (usedIndexes[key] == 1) 
     {
     if (lastTopic != orderedUnits[key]) { firstStyle = "lf"; } else { firstStyle = ""; }
    
     var unitCount = this._Parent.Str.To_Integer(getArrValue(getArrValue(city.units, ukey), "count", 0), 0);
      
     if (config["upkeeps"][key] == undefined)
      {
      cityUpkeep = '?';
      }
     else if (cityUpkeep != '?')
      {
      if (isArmy(key))
       {
       cityUpkeep += applyUpkeepBonus(config["upkeeps"][key]*unitCount,ArmyUpkeepBonus);
       }
      else if (isFleet(key))
       {
       cityUpkeep += applyUpkeepBonus(config["upkeeps"][key]*unitCount,FleetUpkeepBonus);
       }
      }
      
     if (unitCount == 0)
      {
      unitCount = "-";
      }
     else
      {
      sum[key] = (sum[key] == undefined) ? unitCount : sum[key] + unitCount;
      }
      
     var unitConstructionHTML = '<font class="More">-</font>';
     var unitConstruction = this._Parent.Str.To_Integer(getArrValue(getArrValue(city.units, ukey, undefined), "construction", 0), 0);
     
     if (config["upkeeps"][key] == undefined)
      {
      cityConstructionUpkeep = '?';
      }
     else if (cityConstructionUpkeep != '?')
      {
      if (isArmy(key))
       {
       cityConstructionUpkeep += applyUpkeepBonus(config["upkeeps"][key]*unitConstruction,ArmyUpkeepBonus);
       }
      else if (isFleet(key))
       {
       cityConstructionUpkeep += applyUpkeepBonus(config["upkeeps"][key]*unitConstruction,FleetUpkeepBonus);
       }
      }
      
     if (unitConstruction > 0)
      {
      unitConstructionHTML = '<font class="More" title="'+this._Parent.Intl.TT("currentlyBuilding")+'">'+this._Parent.Str.FormatBigNumber(unitConstruction, true)+'</font>';
      sumConstruction[key] = (sumConstruction[key] == undefined) ? unitConstruction : sumConstruction[key] + unitConstruction;
      }
     
     s += "<td unit='"+key+"' class='"+firstStyle+" "+key+"'>"+
          this._Parent.Str.FormatBigNumber(unitCount)+
          unitConstructionHTML+
          "</td>";
    
     lastTopic = orderedUnits[key];
     }
    }
   }
  else s += "<td class='lf'></td><td></td><td></td><td></td><td></td><td></td><td></td>";
  
  if (sumUpkeep != '?')
   {
   if (cityUpkeep != '?')
    {
    sumUpkeep += cityUpkeep;
    }
   else sumUpkeep = '?';
   }
  if (cityUpkeep == 0) cityUpkeep = '-';
  
  if (sumConstructionUpkeep != '?')
   {
   if (cityConstructionUpkeep != '?')
    {
    sumConstructionUpkeep += cityConstructionUpkeep;
    }
   else sumConstructionUpkeep = '?';
   }
  if (cityConstructionUpkeep == 0) cityConstructionUpkeep = '-';
  
  s += "<td class='upkeep lf'>"+(cityUpkeep != '-' ? this._Parent.Str.FormatBigNumber(-1*Math.round(cityUpkeep), true) : cityUpkeep)+"<font class='More'>"+(cityConstructionUpkeep != '-' ? this._Parent.Str.FormatBigNumber(-1*Math.round(cityConstructionUpkeep), true) : cityConstructionUpkeep)+"</font></td>";
  
  s += "</tr>";
  i++;
  if (odd == '') { odd = 'odd'; } else { odd = ''; }
  }
  
 s += "</tbody>";
 
 //s += "<tbody class='foreignCities'>";
 //s += "</tbody>";
 
 s += "<tfoot class='Summary'>";
 
 s += "<tr class='Units'>";
 
 s += "<td class='sigma' colspan=2><img vspace=2 hspace=5 src='skin/layout/sigma.gif'></td>";
 if (usedIndexesCount > 0)
  {
  var firstStyle = "";
  var lastTopic = '';
  for(key in orderedUnits)
   {
   if (usedIndexes[key] == 1)
    {
    if (lastTopic != orderedUnits[key]) { firstStyle = "lf"; } else { firstStyle = ""; }

    var unitConstructionHTML = '<font class="More">-</font>';
    if (sumConstruction[key] > 0)
     {
     unitConstructionHTML = '<font class="More">'+this._Parent.Str.FormatBigNumber(sumConstruction[key], true)+'</font>';
     }
    s += "<td unit='"+key+"' class='"+firstStyle+" "+key+"'>"+
        (sum[key] == undefined ? '-' : this._Parent.Str.FormatBigNumber(sum[key]))+
        unitConstructionHTML+
        "</td>";

    lastTopic = orderedUnits[key];
    }
   }
  }
 else s += "<td class='lf'></td><td></td><td></td><td></td><td></td><td></td><td></td>";
 
 if (sumUpkeep == 0) sumUpkeep = '-';
 if (sumConstructionUpkeep == 0) sumConstructionUpkeep = '-';
 s += "<td class='upkeep lf'>"+(sumUpkeep != '-' ? this._Parent.Str.FormatBigNumber(-1*Math.round(sumUpkeep), true) : sumUpkeep)+"<font class='More'>"+(sumConstructionUpkeep != '-' ? this._Parent.Str.FormatBigNumber(-1*Math.round(sumConstructionUpkeep), true) : sumConstructionUpkeep)+"</font></td>";
 
 s += "</tr>";
 
 s += "</tfoot>";
 
 s += "</table>";
 
 return s;
 };
 
EmpireBoard.Renders.Set_Common_Styles = function()
 {
 var default_style = <><![CDATA[
 #EmpireBoard {
  width: 990px;
  margin: -15px auto 20px;
  }
 
 #EmpireBoard.LtoR,
 #EmpireBoard.LtoR * {
  direction: ltr;
  }
 
 #EmpireBoard.RtoL,
 #EmpireBoard.RtoL * {
  direction: rtl;
  }
 
 #EmpireBoard div.Table {
  margin-bottom: 2px;
  }
 
 #EmpireBoard table.Overview {
  width: 100% !important;
  margin-bottom: 2px;
  background-color: #FDF7DD;
  text-align: center;
  border-collapse: collapse;
  border: 3px double #CB9B6A;
  
  -moz-box-shadow: 3px 3px 7px rgba(93, 72, 41,0.50); 
  -webkit-box-shadow: 3px 3px 7px rgba(93, 72, 41,0.50);
  box-shadow: 3px 3px 7px rgba(93, 72, 41,0.50);
  }
  
 #EmpireBoard table.Overview thead {
  background: #F8E7B3 url(skin/input/button.gif) repeat-x 

0 comments:

Post a Comment