Simple test script

Give a table to help manage cities

  1. // ==UserScript==
  2. // @name Simple test script
  3. // @namespace http://userscripts.org/users/465541
  4. // @description Give a table to help manage cities
  5. // @grant GM_getValue
  6. // @grant GM_setValue
  7. // @grant GM_addStyle
  8. // @grant GM_registerMenuCommand
  9. // @grant GM_deleteValue
  10. // @grant GM_xmlhttpRequest
  11. // @grant GM_openInTab
  12. // @include http://s*.ikariam.*/*
  13. // @exclude http://board.*.ikariam.com*
  14. // @exclude http://*.ikariam.*/board
  15. // @version 0.6.2.000
  16. //
  17. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js
  18. // @require http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js
  19. //
  20. // @history 0.001 script creation
  21. // ==/UserScript==
  22.  
  23. /***********************************************************************************************************************
  24. * Includes
  25. ********************************************************************************************************************* */
  26. ;(function($){
  27. var jQuery = $;
  28.  
  29. if(window.navigator.vendor.match(/Google/)) {
  30. var isChrome = true;
  31. }
  32. if(!isChrome) {
  33. this.$ = this.jQuery = jQuery.noConflict(true);
  34. }
  35.  
  36. $.extend({
  37. exclusive : function(arr) {
  38. return $.grep(arr, function(v, k) {
  39. return $.inArray(v, arr) === k;
  40. });
  41. },
  42. /**
  43. * Updates existing props in (a) with values of props from param[2..n]. Recursing over child objects
  44. * @param {object} a Object to update
  45. * @param {object} b Object containing values merge into param1
  46. * @param {object} c Other objects containing values
  47. * @return {object} Modified original object
  48. */
  49. mergeValues : function(a, b, c) {
  50. var length = arguments.length;
  51. if(length == 1 || typeof arguments[0] !== "object" || typeof arguments[1] !== "object") {
  52. return arguments[0];
  53. }
  54. var args = jQuery.makeArray(arguments);
  55. var i = 1;
  56. var target = args[0];
  57. for(; i < length; i++) {
  58. var copy = args[i];
  59. for(var name in copy) {
  60. if(!target.hasOwnProperty(name)) {
  61. target[name] = copy[name];
  62. continue;
  63. }
  64. if(typeof target[name] == "object" && typeof copy[name] == "object") {
  65. target[name] = jQuery.mergeValues(target[name], copy[name])
  66. } else if(copy.hasOwnProperty(name) && copy[name] != undefined) {
  67. target[name] = copy[name]
  68. }
  69. }
  70. }
  71. return target
  72. },
  73. decodeUrlParam: function(string) {
  74. var str = string.split('?').pop().split('&');
  75. var obj = {};
  76. for(var i = 0; i < str.length; i++) {
  77. var param = str[i].split('=');
  78. if(param.length !== 2) {
  79. continue;
  80. }
  81. obj[param[0]] = decodeURIComponent(param[1].replace(/\+/g, " "))
  82. }
  83. return obj
  84. }
  85. });
  86.  
  87. var events = (function() {
  88. var _events = {};
  89. var retEvents = function(id) {
  90. var callbacks, topic = id && _events[ id ];
  91. if(!topic) {
  92. callbacks = $.Callbacks("");
  93. topic = {
  94. pub : callbacks.fire,
  95. sub : callbacks.add,
  96. unsub: callbacks.remove
  97. };
  98. if(id) {
  99. _events[ id ] = topic;
  100. }
  101. }
  102. return topic;
  103. };
  104. /**
  105. * Call a function <tt>time</tt> (ms) in the future
  106. * @param {function} callback Function to be called
  107. * @param {number} time Wait time in milliseconds
  108. * @return {function} Function to cancel scheduled callback
  109. */
  110. retEvents.scheduleAction = function(callback, time) {
  111. return clearTimeout.bind(undefined, setTimeout(callback, time || 0));
  112. };
  113. /**
  114. * Call a function at specified DateTime in the future
  115. * @param {function} callback Function to be run
  116. * @param {number} [time=0] DateTime to call function
  117. * @return {function} Function to cancel scheduled callback
  118. */
  119. retEvents.scheduleActionAtTime = function(callback, time) {
  120. return retEvents.scheduleAction(callback, (time - $.now() > 0 ? time - $.now() : 0))
  121. };
  122. /**
  123. * Call a function every <tt>time</tt> (ms) in the future
  124. * @param {function} Function to be called
  125. * @param {number} Wait time in milliseconds between calls
  126. * @return {function} Function to clear the recurring event
  127. */
  128. retEvents.scheduleActionAtInterval = function(callback, time) {
  129. return clearInterval.bind(undefined, setInterval(callback, time));
  130. };
  131. return retEvents
  132. })();
  133. /***********************************************************************************************************************
  134. * Globals
  135. **********************************************************************************************************************/
  136. var debug = false;
  137. var log = false; // SITR logging pane
  138. var timing = false;
  139. if(!unsafeWindow) unsafeWindow = window;
  140. /***********************************************************************************************************************
  141. * Inject button into page before the page renders the YUI menu or it will not be animated (less work)
  142. **********************************************************************************************************************/
  143. $('.menu_slots > .expandable:last').after('<li class="expandable slot99 SITR_Menu" onclick=""><div class="SITR_Menu2 image" style="background-image: url(data:image/png;base64,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); background-position:center center; background-size:122% 122%"></div></div><div class="name"><span class="namebox">SITR Resource Overview</span></div></li>');
  144.  
  145. //TODO Replace Army/Building table rendering with a per row $('row').replaceWith(newRow) on data change
  146. //TODO Replace Resource table continuous rendering with 'resource only' updates and cell/row level replaceWith as above on various changes
  147.  
  148. /***********************************************************************************************************************
  149. * Utility Functions
  150. **********************************************************************************************************************/
  151. var Utils = {
  152. wrapInClosure : function(obj) {
  153. return (function(x) {
  154. return function() {
  155. return x
  156. }
  157. })(obj)
  158. },
  159. existsIn : function(input, test) {
  160. try {
  161. var ret = input.indexOf(test) !== -1
  162. } catch(e) {
  163. return false
  164. }
  165. return ret;
  166. },
  167. estimateTravelTime: function(city1, city2) {
  168. if(!city1 || !city2) return 0;
  169. if(city1[0] == city2[0] && city1[1] == city2[1]) {
  170. var time = 1200 / 60 * 0.5;
  171. } else {
  172. time = 1200 / 60 * (Math.sqrt(Math.pow((city2[0] - city1[0]), 2) + Math.pow((city2[1] - city1[1]), 2)));
  173. }
  174. return Math.floor(time * 60 * 1000);
  175. },
  176. addStyleSheet : function(style) {
  177. var getHead = document.getElementsByTagName("HEAD")[0];
  178. var cssNode = window.document.createElement('style');
  179. var elementStyle = getHead.appendChild(cssNode);
  180. elementStyle.innerHTML = style;
  181. return elementStyle;
  182. },
  183. escapeRegExp : function(str) {
  184. return str.replace(/[\[\]\/\{\}\(\)\-\?\$\*\+\.\\\^\|]/g, "\\$&");
  185. },
  186. /**
  187. * Replaces '{key}' in inputString with 'value' from replacements, can take objects or arrays
  188. * @param inputString [string] input text to be transformed
  189. * @param replacements [object] object containing key/value pairs to replace
  190. * @return {*}
  191. */
  192. format : function(inputString, replacements) {
  193. var str = '' + inputString;
  194. var keys = Object.keys(replacements);
  195. var i = keys.length;
  196. while(i--) {
  197. str = str.replace(new RegExp(this.escapeRegExp('{' + keys[i] + '}'), 'g'), replacements[keys[i]])
  198. }
  199. return str
  200. },
  201. cacheFunction : function(toExecute, expiry) {
  202. expiry = expiry || 1000;
  203. var cachedTime = $.now;
  204. var cachedResult = undefined;
  205. return function() {
  206. if(cachedTime < $.now() - expiry || cachedResult === undefined) {
  207. cachedResult = toExecute();
  208. cachedTime = $.now()
  209. }
  210. return cachedResult
  211. }
  212. },
  213. getClone : function($node){
  214. if ($node.hasClass('ui-sortable-helper') || $node.parent().find('.ui-sortable-helper').length){
  215. return $node;}
  216. return $($node.get(0).cloneNode(true))
  217. },
  218. setClone : function($node, $clone){
  219. if ($node.hasClass('ui-sortable-helper') || $node.parent().find('.ui-sortable-helper').length){
  220. return $node;
  221. }
  222. $node.get(0).parentNode.replaceChild($clone.get(0), $node.get(0));
  223. return $node
  224. },
  225. replaceNode : function(node, html) {
  226. var t = node.cloneNode(false);
  227. t.innerHTML = html;
  228. node.parentNode.replaceChild(t, node);
  229. return t
  230. },
  231. FormatTimeLengthToStr : function(timeString, precision, spacer) {
  232. timeString = timeString || 0;
  233. precision = precision || 2;
  234. spacer = spacer || " ";
  235. if(!isFinite(timeString)) {
  236. return ' \u221E ';
  237. }
  238. if(timeString < 0) timeString *= -1;
  239. var factors = [];
  240. var locStr = [];
  241. factors.day = 86400;
  242. factors.hour = 3600;
  243. factors.minute = 60;
  244. factors.second = 1;
  245. locStr.day = database.getGlobalData.getLocalisedString('day');
  246. locStr.hour = database.getGlobalData.getLocalisedString('hour');
  247. locStr.minute = database.getGlobalData.getLocalisedString('minute');
  248. locStr.second = database.getGlobalData.getLocalisedString('second');
  249. timeString = Math.ceil(timeString / 1000);
  250. var retString = "";
  251. for(var fact in factors) {
  252. var timeInSecs = Math.floor(timeString / factors[fact]);
  253. if(isNaN(timeInSecs)) {
  254. return retString;
  255. }
  256. if(precision > 0 && (timeInSecs > 0 || retString != "")) {
  257. timeString = timeString - timeInSecs * factors[fact];
  258. if(retString != "") {
  259. retString += spacer;
  260. }
  261. retString += timeInSecs + locStr[fact];
  262. precision--;
  263. }
  264. }
  265. return retString;
  266. },
  267. FormatFullTimeToDateString: function (timeString, precise) {
  268. precise = precise || true;
  269. timeString = timeString || 0;
  270. var sInDay = 86400000;
  271. var day = '';
  272. var compDate = new Date(timeString);
  273. if(precise) {
  274. switch(Math.floor(compDate.getTime() / sInDay) - Math.floor($.now() / sInDay)) {
  275. case 0 :
  276. day = database.getGlobalData.getLocalisedString('Today');
  277. break;
  278. case 1 :
  279. day = database.getGlobalData.getLocalisedString('Tomorrow');
  280. break;
  281. case -1 :
  282. day = database.getGlobalData.getLocalisedString('Yesterday');
  283. break;
  284. default :
  285. day = (!isChrome ? compDate.toLocaleFormat('%a %d %b') : compDate.toString().split(' ').splice(0, 5).join(' '))
  286. }
  287. }
  288. if(day != '') {
  289. day += ', '
  290. }
  291. return day + compDate.toLocaleTimeString();
  292. },
  293. FormatRemainingTime : function(time, brackets) {
  294. brackets = brackets || false;
  295. var arrInTime = Utils.FormatTimeLengthToStr(time, 3, ' ');
  296. return (arrInTime == '') ? '' : (brackets ? '(' : '') + arrInTime + (brackets ? ')' : '');
  297. },
  298. FormatNumToStr : function(inputNum, outputSign, precision) {
  299. precision = precision ? "10e" + (precision - 1) : 1;
  300. var ret, val, sign, i, j;
  301. var tho = database.getGlobalData.getLocalisedString('thousandSeperator');
  302. var dec = database.getGlobalData.getLocalisedString('decimalPoint');
  303. if(!isFinite(inputNum)) {
  304. return '\u221E'
  305. }
  306. sign = inputNum > 0 ? 1 : inputNum === 0 ? 0 : -1;
  307. if(sign) {
  308. val = (( Math.floor(Math.abs(inputNum * precision)) / precision ) + '').split('.');
  309. ret = val[1] != undefined ? [dec, val[1]] : [];
  310. val = val[0].split('');
  311. i = val.length;
  312. j = 1;
  313. while(i--) {
  314. ret.unshift(val.pop());
  315. if(i && j % 3 == 0) {
  316. ret.unshift(tho)
  317. }
  318. j++
  319. }
  320. if(outputSign) {
  321. ret.unshift(sign == 1 ? '+' : '-');
  322. }
  323. return ret.join('');
  324. }
  325. else return inputNum;
  326. }
  327. };
  328. /***********************************************************************************************************************
  329. * CLASSES
  330. **********************************************************************************************************************/
  331. function Movement(id, originCityId, targetCityId, arrivalTime, mission, loadingTime, resources, military, ships) {
  332. if(typeof id === "object") {
  333. this._id = id._id || null;
  334. this._originCityId = id._originCityId || null;
  335. this._targetCityId = id._targetCityId || null;
  336. this._arrivalTime = id._arrivalTime || null;
  337. this._mission = id._mission || null;
  338. this._loadingTime = id._loadingTime || null;
  339. this._resources = id._resources || {wood: 0, wine: 0, marble: 0, glass: 0, sulfur: 0};
  340. this._military = id._military || new MilitaryUnits();
  341. this._ships = id._ships || null;
  342. this._updatedCity = id._updatedCity || false;
  343. this._complete = id._complete || false;
  344. this._updateTimer = id._updateTimer || null;
  345.  
  346. } else {
  347. this._id = id || null;
  348. this._originCityId = originCityId || null;
  349. this._targetCityId = targetCityId || null;
  350. this._arrivalTime = arrivalTime || null;
  351. this._mission = mission || null;
  352. this._loadingTime = loadingTime || null;
  353. this._resources = resources || {wood: 0, wine: 0, marble: 0, glass: 0, sulfur: 0};
  354. this._military = military || new MilitaryUnits();
  355. this._ships = ships || null;
  356. this._updatedCity = false;
  357. this._complete = false;
  358. this._updateTimer = null;
  359. }
  360. }
  361. Movement.prototype = {
  362. startUpdateTimer : function() {
  363. this.clearUpdateTimer();
  364. if(this.isCompleted) {
  365. this.updateTransportComplete()
  366. } else {
  367. this._updateTimer = events.scheduleActionAtTime(this.updateTransportComplete.bind(this), this._arrivalTime + 1000)
  368. }
  369. },
  370. clearUpdateTimer : function() {
  371. var ret = !this._updateTimer || this._updateTimer();
  372. this._updateTimer = null;
  373. return ret
  374. },
  375. get getId() {
  376. return this._id
  377. },
  378. get getOriginCityId() {
  379. return this._originCityId
  380. },
  381. get getTargetCityId() {
  382. return this._targetCityId
  383. },
  384. get getArrivalTime() {
  385. return this._arrivalTime
  386. },
  387. get getMission() {
  388. return this._mission
  389. },
  390. get getLoadingTime() {
  391. return this._loadingTime - $.now()
  392. },
  393. get getResources() {
  394. return this._resources
  395. },
  396. getResource : function(resourceName) {
  397. return this._resources[resourceName]
  398. },
  399. get getMilitary() {
  400. return this._military
  401. },
  402. get getShips() {
  403. return this._ships
  404. },
  405. get isCompleted() {
  406. return this._arrivalTime < $.now()
  407. },
  408. get isLoading() {
  409. return this._loadingTime > $.now()
  410. },
  411. get getRemainingTime() {
  412. return this._arrivalTime - $.now()
  413. },
  414. updateTransportComplete: function() {
  415. if(this.isCompleted && !this._updatedCity) {
  416. var city = database.getCityFromId(this._targetCityId);
  417. var changes = [];
  418. if(city) {
  419. for(var resource in Constant.Resources) {
  420. if(this.getResource(Constant.Resources[resource])) {
  421. changes.push(Constant.Resources[resource])
  422. }
  423. city.getResource(Constant.Resources[resource]).increment(this.getResource(Constant.Resources[resource]));
  424. }
  425. this._updatedCity = true;
  426. city = database.getCityFromId(this.originCityId);
  427. if(city) {
  428. city.updateActionPoints(city.getAvailableActions + 1)
  429. }
  430. //TODO: Military
  431.  
  432. if(changes.length) {
  433. events(Constant.Events.MOVEMENTS_UPDATED).pub([this.getTargetCityId]);
  434. events(Constant.Events.RESOURCES_UPDATED).pub(this.getTargetCityId, changes);
  435. }
  436. events.scheduleAction(function() {
  437. database.getGlobalData.removeFleetMovement(this._id)
  438. }.bind(this));
  439. return true
  440. }
  441.  
  442. } else if(this._updatedCity) {
  443. events.scheduleAction(function() {
  444. database.getGlobalData.removeFleetMovement(this._id)
  445. }.bind(this))
  446. }
  447. return false;
  448. }
  449. };
  450.  
  451. function Resource(city, name) {
  452. this._current = 0;
  453. this._production = 0;
  454. this._consumption = 0;
  455. this._currentChangedDate = $.now();
  456. this.city = Utils.wrapInClosure(city);
  457. this._name = name;
  458. return this
  459. }
  460.  
  461. Resource.prototype = {
  462. get name() {
  463. return this._name
  464. },
  465. update : function(current, production, consumption) {
  466. var changed = (current % this._current > 10) || (production != this._production) || (consumption != this._consumption);
  467. this._current = current;
  468. this._production = production;
  469. this._consumption = consumption;
  470. this._currentChangedDate = $.now();
  471. return changed;
  472. },
  473. project : function() {
  474. var limit = Math.floor($.now() / 1000);
  475. var start = Math.floor(this._currentChangedDate / 1000);
  476. while(limit > start) {
  477. this._current += this._production;
  478. if(Math.floor(start / 3600) != Math.floor((start + 1) / 3600))
  479. if(this._current > this._consumption) {
  480. this._current -= this._consumption
  481. } else {
  482. this.city().projectPopData(start * 1000);
  483. this._consumption = 0;
  484. }
  485.  
  486. start++
  487. }
  488. this._currentChangedDate = limit * 1000;
  489. this.city().projectPopData(limit * 1000)
  490.  
  491. },
  492. increment: function(amount) {
  493. if(amount !== 0) {
  494. this._current += amount;
  495. return true;
  496. }
  497. return false;
  498. },
  499. get getEmptyTime() {
  500. var net = this.getProduction * 3600 - this.getConsumption;
  501. return (net < 0) ? this.getCurrent / net * -1 : Infinity; //no consumption == never empty
  502. },
  503. get getFullTime() {
  504. var net = this.getProduction * 3600 - this.getConsumption;
  505. return (net > 0) ? (this.city().maxResourceCapacities.capacity - this.getCurrent) / net : 0;//no production == never full ?
  506. },
  507. get getCurrent() {
  508. return Math.floor(this._current);
  509.  
  510. },
  511. get getProduction() {
  512. return this._production || 0
  513. }, //per hour
  514. get getConsumption() {
  515. return this._consumption || 0
  516. } //per hour
  517. };
  518.  
  519. function Military(city) {
  520. this.city = Utils.wrapInClosure(city);
  521. this._units = new MilitaryUnits();
  522. this._advisorLastUpdate = 0;
  523.  
  524. this.armyTraining = [];
  525. this._trainingTimer = null;
  526. }
  527. Military.prototype = {
  528. init : function() {
  529. this._trainingTimer = null;
  530. this._startTrainingTimer()
  531. },
  532. _getTrainingTotals: function (){
  533. var ret = {};
  534. $.each(this.armyTraining, function(index, training) {
  535. $.each(Constant.UnitData, function(unitId, info) {
  536. ret[unitId] = ret[unitId]?ret[unitId]+(training.units[unitId]||0):training.units[unitId]||0
  537. })
  538. });
  539. return ret
  540. },
  541. get getTrainingTotals() { //cached
  542. if(!this._trainingTotals) {
  543. this._trainingTotals = Utils.cacheFunction(this._getTrainingTotals.bind(this), 1000)
  544. }
  545. return this._trainingTotals()
  546. },
  547. _getIncomingTotals :function (){
  548. var ret = {};
  549. $.each(this.city().getIncomingMilitary, function(index, element) {
  550. for(var unitName in Constant.UnitData) {
  551. ret[unitName] = ret[unitName]?ret[unitName]+(element.getMilitary.totals[unitName]||0):element.getMilitary.totals[unitName]||0;
  552. }
  553. });
  554. return ret
  555. },
  556. get getIncomingTotals() { //cached
  557. if(!this._incomingTotals) {
  558. this._incomingTotals = Utils.cacheFunction(this._getIncomingTotals.bind(this), 1000)
  559. }
  560. return this._incomingTotals()
  561. },
  562. getTrainingForUnit : function(unit) {
  563. var ret = [];
  564. $.each(this.armyTraining, function(index, training) {
  565. $.each(training.units, function(unitId, count) {
  566. if(unitId === unit) {
  567. ret.push({count: count, time: training.completionTime})
  568. }
  569. })
  570. });
  571. return ret
  572. },
  573. setTraining : function(trainingQueue) {
  574. if(!trainingQueue.length) return false;
  575.  
  576. this._stopTrainingTimer();
  577.  
  578. var type = trainingQueue[0].type;
  579. var changes = this._clearTrainingForType(type);
  580. $.each(trainingQueue, function(index, training) {
  581. this.armyTraining.push(training);
  582. $.each(training.units, function(unitId, count) {
  583. changes.push(unitId)
  584. })
  585. }.bind(this));
  586. this.armyTraining.sort(function(a, b) {
  587. return a.completionTime - b.completionTime
  588. });
  589. this._startTrainingTimer();
  590. return $.exclusive(changes)
  591. },
  592. _clearTrainingForType: function(type) {
  593. var oldTraining = this.armyTraining.filter(function(item) {
  594. return item.type === type
  595. });
  596. this.armyTraining = this.armyTraining.filter(function(item) {
  597. return item.type !== type
  598. });
  599. var changes = [];
  600. $.each(oldTraining, function(index, training) {
  601. $.each(training.units, function(unitId, count) {
  602. changes.push(unitId)
  603. })
  604. });
  605. return changes
  606. },
  607. _completeTraining : function() {
  608. if(this.armyTraining.length) {
  609. if(this.armyTraining[0].completionTime < $.now() + 5000) {
  610. var changes = [];
  611. var training = this.armyTraining.shift();
  612. $.each(training.units, function(id, count) {
  613. this.getUnits.addUnit(id, count);
  614. changes.push(id)
  615. }.bind(this));
  616. if(changes.length)events(Constant.Events.MILITARY_UPDATED).pub(this.city().getId, changes)
  617. }
  618. }
  619. this._startTrainingTimer()
  620. },
  621. _startTrainingTimer : function() {
  622. this._stopTrainingTimer();
  623. if(this.armyTraining.length) {
  624. this._trainingTimer = events.scheduleActionAtTime(this._completeTraining.bind(this), this.armyTraining[0].completionTime)
  625.  
  626. }
  627. },
  628. _stopTrainingTimer : function() {
  629. if(this._trainingTimer) {
  630. this._trainingTimer()
  631. }
  632. this._trainingTimer = null
  633. },
  634. updateUnits : function(counts) {
  635. var changes = [];
  636. $.each(counts, function(unitId, count) {
  637. if(this._units.setUnit(unitId, count)) {
  638. changes.push(unitId)
  639. }
  640. }.bind(this));
  641. return changes;
  642. },
  643. get getUnits() {
  644. return this._units
  645. }
  646. };
  647. function MilitaryUnits(obj) {
  648. this._units = obj !== undefined ? obj._units: {};
  649. }
  650. MilitaryUnits.prototype = {
  651. getUnit : function(unitId) {
  652. return this._units[unitId] || 0
  653. },
  654. setUnit : function(unitId, count) {
  655. var changed = this._units[unitId] != count;
  656. this._units[unitId] = count;
  657. return changed
  658. },
  659. get totals() {
  660. return this._units
  661. },
  662. addUnit : function(unitId, count) {
  663. return this.setUnit(unitId, this.getUnit(unitId) + count)
  664. },
  665. removeUnit: function(unitId, count) {
  666. count = Math.max(0, this.getUnit[unitId] - count);
  667. return this.setUnit(unitId, count)
  668. }
  669.  
  670. };
  671. function Building(city, pos) {
  672. this._position = pos;
  673. this._level = 0;
  674. this._name = null;
  675. this.city = Utils.wrapInClosure(city);
  676. this._updateTimer = null
  677. }
  678. Building.prototype = {
  679. startUpgradeTimer : function() {
  680. if(this._updateTimer) {
  681. this._updateTimer();
  682. delete this._updateTimer
  683. }
  684. if(this._completionTime) {
  685. if(this._completionTime - $.now() < 5000) {
  686. this.completeUpgrade()
  687. } else {
  688. this._updateTimer = events.scheduleActionAtTime(this.completeUpgrade.bind(this), this._completionTime - 4000)
  689. }
  690. }
  691.  
  692. var statusPoll = function(a, b){
  693. return events.scheduleActionAtInterval(function(){
  694. if(a != this.isUpgradable || b != this.isUpgrading){
  695. var changes = {position: this._position, name: this.getName, upgraded: this.isUpgrading != b}
  696. events(Constant.Events.BUILDINGS_UPDATED).pub([changes]);
  697. a = this.isUpgradable;
  698. b = this.isUpgrading;
  699. }
  700. }.bind(this),3000)
  701. }(this.isUpgradable,this.isUpgrading)
  702. },
  703. update : function(data) {
  704. var changes;
  705. var name = data.building.split(' ')[0];
  706. var level = parseInt(data.level) || 0;
  707. database.getGlobalData.addLocalisedString(name, data.name); //Todo: snip for translation
  708. var completion = ('undefined' !== typeof data['completed']) ? parseInt(data['completed']) : 0;
  709. var changed = (name !== this._name || level !== this._level || !!completion != this.isUpgrading);
  710. if(changed) {
  711. changes = {position: this._position, name: this.getName, upgraded: this.isUpgrading != !completion};
  712. }
  713. if(completion) {
  714. this._completionTime = completion * 1000;
  715. this.startUpgradeTimer()
  716. } else if(this._completionTime) {
  717. delete this._completionTime
  718. }
  719. this._name = name;
  720. this._level = level;
  721. if(changed) {
  722. return changes;
  723. }
  724. return false;
  725. },
  726. get getUrlParams() {
  727. return {
  728. view : this.getName,
  729. cityId : this.city().getId,
  730. position: this.getPosition
  731. };
  732. //+'&currentCityId=351633'
  733. },
  734. get getUpgradeCost() {
  735. var carpenter, architect, vineyard, fireworker, optician;
  736. var level = this._level + this.isUpgrading;
  737. if(this.isEmpty) {
  738. return {
  739. wood : Infinity,
  740. glass : 0,
  741. marble: 0,
  742. sulfur: 0,
  743. wine : 0,
  744. time : 0
  745. }
  746. }
  747. var time = Constant.BuildingData[this._name].time;
  748. var bon = 1;
  749. var bonTime = 1 + Constant.GovernmentData[database.getGlobalData.getGovernmentType].buildingTime;
  750. bon -= database.getGlobalData.getResearchTopicLevel(Constant.Research.Economy.PULLEY) ? .02 : 0;
  751. bon -= database.getGlobalData.getResearchTopicLevel(Constant.Research.Economy.GEOMETRY) ? .04 : 0;
  752. bon -= database.getGlobalData.getResearchTopicLevel(Constant.Research.Economy.SPIRIT_LEVEL) ? .08 : 0;
  753. return{
  754. wood : Math.floor((Constant.BuildingData[this._name].wood[level] || 0) * (bon - (carpenter = this.city().getBuildingFromName(Constant.Buildings.CARPENTER), carpenter ? carpenter.getLevel / 100 : 0))),
  755. glass : Math.floor((Constant.BuildingData[this._name].glass[level] || 0) * (bon - (optician = this.city().getBuildingFromName(Constant.Buildings.OPTICIAN), optician ? optician.getLevel / 100 : 0))),
  756. marble: Math.floor((Constant.BuildingData[this._name].marble[level] || 0) * (bon - (architect = this.city().getBuildingFromName(Constant.Buildings.ARCHITECT), architect ? architect.getLevel / 100 : 0))),
  757. sulfur: Math.floor((Constant.BuildingData[this._name].sulfur[level] || 0) * (bon - (fireworker = this.city().getBuildingFromName(Constant.Buildings.FIREWORK_TEST_AREA), fireworker ? fireworker.getLevel / 100 : 0))),
  758. wine : Math.floor((Constant.BuildingData[this._name].wine[level] || 0) * (bon - (vineyard = this.city().getBuildingFromName(Constant.Buildings.VINEYARD), vineyard ? vineyard.getLevel / 100 : 0))),
  759. time: Math.round(time.a / time.b * Math.pow(time.c, level + 1) - time.d) * 1000 * bonTime
  760. }
  761. },
  762. get getName() {
  763. return this._name
  764. },
  765. get getType() {
  766. return Constant.BuildingData[this.getName].type
  767. },
  768. get getLevel() {
  769. return this._level
  770. },
  771. get isEmpty() {
  772. return this._name == 'buildingGround' || this._name == null
  773. },
  774. get isUpgrading() {
  775. return (this._completionTime > $.now())
  776. },
  777. subtractUpgradeResourcesFromCity: function() {
  778. var cost = this.getUpgradeCost;
  779. $.each(Constant.Resources, function(key, resourceName) {
  780. this.city().getResource(resourceName).increment(cost[resourceName] * -1)
  781. }.bind(this));
  782. this._completionTime = $.now() + cost.time;
  783. //this.startUpgradeTimer()
  784.  
  785. },
  786. get isUpgradable() {
  787. if(this.isEmpty || this.isMaxLevel) {
  788. return false
  789. }
  790. var cost = this.getUpgradeCost;
  791. var upgradable = true;
  792. $.each(Constant.Resources, function(key, value) {
  793. upgradable = upgradable && (!cost[value] || cost[value] <= this.city().getResource(value).getCurrent);
  794. }.bind(this));
  795. return upgradable;
  796. },
  797. get getCompletionTime() {
  798. return this._completionTime
  799. },
  800. get getCompletionDate() {
  801. },
  802. get isMaxLevel() {
  803. return Constant.BuildingData[this.getName].maxLevel === (this.getLevel + this.isUpgrading)
  804. },
  805. get getPosition() {
  806. return this._position
  807. },
  808. completeUpgrade : function() {
  809. this._level++;
  810. delete this._completionTime;
  811. delete this._updateTimer; //todo: look at this completed field
  812. events(Constant.Events.BUILDINGS_UPDATED).pub(this.city().getId, [
  813. {position: this._position, name: this.getName, upgraded: true}
  814. ])
  815. }
  816. };
  817. function CityResearch(city) {
  818. this._researchersLastUpdate = 0;
  819. this._researchers = 0;
  820. this._researchCostLastUpdate = 0;
  821. this._researchCost = 0;
  822. this.city = Utils.wrapInClosure(city);
  823. }
  824.  
  825. CityResearch.prototype = {
  826. updateResearchers: function(researchers) { //TODO: tidy up
  827. var changed = this._researchers !== researchers;
  828. this._researchers = researchers;
  829. this._researchersLastUpdate = $.now();
  830. this._researchCost = this.getResearchCost;
  831. //if (changed) events(Constant.Events.CITY_UPDATED).pub(this.city().id, {research:changed});
  832. return changed;
  833. },
  834. updateCost : function(cost) { //TODO: tidy up
  835. var changed = this._researchCost !== cost;
  836. this._researchCost = cost;
  837. this._researchCostLastUpdate = $.now();
  838. this._researchers = this.getResearchers;
  839. //if (changed) events(Constant.Events.CITY_UPDATED).pub(this.city().id, {research:changed});
  840. return changed;
  841. },
  842. get getResearchers() {
  843. if(this._researchersLastUpdate < this._researchCostLastUpdate) {
  844. return Math.floor(this._researchCost / this._researchCostModifier);
  845. } else {
  846. return this._researchers
  847. }
  848. },
  849. get getResearch() {
  850. return this.researchData.total;
  851. },
  852. get researchData(){
  853. if (!this._researchData){
  854. this._researchData = Utils.cacheFunction(this.researchDataCached.bind(this),1000)
  855. }
  856. return this._researchData()
  857. },
  858. researchDataCached :function(){
  859. var resBon = 0 + Constant.GovernmentData[database.getGlobalData.getGovernmentType].researchBonus
  860. + (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.PAPER) * 0.02)
  861. + (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.INK) * 0.04)
  862. + (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.MECHANICAL_PEN) * 0.08)
  863. + (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.SCIENTIFIC_FUTURE) * 0.02);
  864.  
  865. var premBon = database.getGlobalData.hasPremiumFeature(Constant.Premium.RESEARCH_POINTS_BONUS_EXTREME_LENGTH)
  866. ?(0 + Constant.PremiumData[Constant.Premium.RESEARCH_POINTS_BONUS_EXTREME_LENGTH].bonus)
  867. :database.getGlobalData.hasPremiumFeature(Constant.Premium.RESEARCH_POINTS_BONUS)
  868. ?(0 + Constant.PremiumData[Constant.Premium.RESEARCH_POINTS_BONUS].bonus)
  869. :0;
  870. var goods = Constant.GovernmentData[database.getGlobalData.getGovernmentType].researchPerCulturalGood * this.city()._culturalGoods;
  871. var researchers = this.getResearchers;
  872. var corruptionSpend = researchers * this.city().getCorruption;
  873. var nonCorruptedResearchers = researchers * (1 - this.city().getCorruption);
  874. var premiumResBonus = nonCorruptedResearchers * premBon;
  875. var researchBonus = nonCorruptedResearchers * resBon;
  876. var premiumGoodsBonus = goods * premBon;
  877.  
  878. return {
  879. scientists: researchers,
  880. researchBonus: researchBonus,
  881. premiumScientistBonus:premiumResBonus,
  882. premiumResearchBonus: (researchBonus* premBon),
  883. culturalGoods: goods,
  884. premiumCulturalGoodsBonus: premiumGoodsBonus,
  885. corruption: corruptionSpend,
  886. total: nonCorruptedResearchers + researchBonus + premiumResBonus + goods + premiumGoodsBonus + (researchBonus* premBon)
  887. }
  888. },
  889. get _researchCostModifier() {
  890. return 6 + Constant.GovernmentData[database.getGlobalData.getGovernmentType].researcherCost - (database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.LETTER_CHUTE) * 3)
  891. },
  892. get getResearchCost() {
  893. return this.getResearchers * this._researchCostModifier;
  894. }
  895. };
  896.  
  897. function Changes(city, type, changes) {
  898. this.city = city || null;
  899. this.type = type || null;
  900. this.changes = changes || [];
  901. }
  902. function Population(city) {
  903. this._population = 0;
  904. this._citizens = 0;
  905. this._resourceWorkers = 0;
  906. this._tradeWorkers = 0;
  907. this._priests = 0;
  908. this._culturalGoods = 0;
  909.  
  910. this._popChanged = $.now();
  911. this._citizensChanged = $.now();
  912. this._culturalGoodsChanged = $.now();
  913. this._priestsChanged = $.now();
  914. this.city = Utils.wrapInClosure(city)
  915. }
  916. Population.prototype = {
  917. updatePopulationData: function(population, citizens, priests, culturalGoods) {
  918. var changes = [];
  919. if(population && population != this._population) {
  920. changes.push({population: true});
  921. this.population = population;
  922. }
  923. if(citizens && citizens != this._priests) {
  924. changes.push({citizens: true});
  925. this.citizens = citizens;
  926. }
  927. if(priests && priests != this._priests) {
  928. changes.push({priests: true});
  929. this.priests = priests;
  930. }
  931. },
  932. updateWorkerData : function(resourceName, workers) {
  933. },
  934. updatePriests : function(newCount) {
  935.  
  936. },
  937. updateCulturalGoods : function(newCount) {
  938. },
  939. get population() {
  940. return this._population
  941. },
  942. set population(newVal) {
  943. this._population = newVal;
  944. this._popChanged = $.now()
  945. },
  946. get citizens() {
  947. return this._citizens
  948. },
  949. set citizens(newVal) {
  950. this._citizens = newVal;
  951. this._citizensChanged = $.now()
  952. },
  953. get priests() {
  954. return this._priests
  955. },
  956. set priests(newVal) {
  957. this._priests = newVal;
  958. this._priestsChanged = $.now()
  959. }
  960. };
  961.  
  962. function City(id) {
  963. this._id = id || 0;
  964. this._name = '';
  965. this._resources = {
  966. wood : new Resource(this, Constant.Resources.WOOD),
  967. wine : new Resource(this, Constant.Resources.WINE),
  968. marble: new Resource(this, Constant.Resources.MARBLE),
  969. glass : new Resource(this, Constant.Resources.GLASS),
  970. sulfur: new Resource(this, Constant.Resources.SULFUR)
  971. };
  972. this._capacities = {
  973. capacity : 0,
  974. safe : 0,
  975. buildings: {
  976. dump : {storage: 0, safe: 0},
  977. warehouse: {storage: 0, safe: 0},
  978. townHall : {storage: 2500, safe: 100}
  979. },
  980. invalid : true
  981. };
  982. this._tradeGoodID = 0;
  983. this.knownTime = $.now();
  984. this._lastPopUpdate = $.now();
  985. this._buildings = new Array(18);
  986. var i = this._buildings.length;
  987. while(i--) {
  988. this._buildings[i] = new Building(this, i)
  989. }
  990. this._research = new CityResearch(this);
  991. this._actionPoints = 0;
  992. this._coordinates = {x: 0, y: 0};
  993. this._islandID = null;
  994.  
  995. this.population = new Population(this);
  996. //Todo: make population class
  997. this._population = 0;
  998. this._citizens = 0;
  999. this._resourceWorkers = 0;
  1000. this._tradeWorkers = 0;
  1001. this._priests = 0;
  1002. this._culturalGoods = 0;
  1003.  
  1004. this._military = new Military(this);
  1005.  
  1006. this.fleetMovements = {};
  1007. this.militaryMovements = {};
  1008. this.unitBuildList = [];
  1009. //TODO: Finances
  1010. this.goldIncome = 0;
  1011. this.goldExpend = 0;
  1012.  
  1013. this._pop = {currentPop: 0, maxPop: 0, satisfaction: {city: 196, museum: {cultural: 0, level: 0}, government: 0, tavern: {wineConsumption: 0, level: 0}, research: 0, priest: 0, total: 0}, happiness: 0, growth: 0};
  1014. events('updateCityData').sub(this.updateCityDataFromAjax.bind(this));
  1015. events('updateBuildingData').sub(this.updateBuildingsDataFromAjax.bind(this));
  1016. }
  1017.  
  1018. City.prototype = {
  1019. init : function() {
  1020. $.each(this._buildings, function(idx, building) {
  1021. building.startUpgradeTimer()
  1022. });
  1023. this.military.init();
  1024. $.each(this._resources, function(resourceName, resource) {
  1025. resource.project()
  1026. });
  1027. events.scheduleActionAtInterval(function() {
  1028. $.each(this._resources, function(resourceName, resource) {
  1029. resource.project()
  1030. }.bind(this))
  1031. }.bind(this), 1000);
  1032. },
  1033. projectResource : function(seconds) {
  1034. //$.each(this._resources, function (resourceName, resource){resource.project(seconds)})
  1035. },
  1036. updateBuildingsDataFromAjax: function(id, position) {
  1037. var changes = [];
  1038. if(id == this.getId && ikariam.viewIsCity) {
  1039. if(position) {
  1040. $.each(position, function(i, item) {
  1041. var change = this.getBuildingFromPosition(i).update(item);
  1042. if(change) changes.push(change);
  1043. }.bind(this));
  1044. if(changes.length) {
  1045. this._capacities.invalid = true;
  1046. events(Constant.Events.BUILDINGS_UPDATED).pub(id, changes)
  1047. }
  1048. }
  1049. }
  1050. },
  1051. updateCityDataFromAjax : function(id, cityData) {
  1052. var resourcesChanged = false;
  1053. var changes = {};
  1054. if(id == this.getId) {
  1055. try {
  1056. var baseWineConsumption = 0, wineConsumption = 0;
  1057. if($.inArray(cityData.wineSpendings, Constant.BuildingData[Constant.Buildings.TAVERN].wineUse) > -1) {
  1058. baseWineConsumption = cityData.wineSpendings;
  1059. wineConsumption = (this.getBuildingFromName(Constant.Buildings.VINEYARD)) ? baseWineConsumption * ((100 - this.getBuildingFromName(Constant.Buildings.VINEYARD).getLevel) / 100) : baseWineConsumption;
  1060. } else {
  1061. wineConsumption = cityData.wineSpendings
  1062. }
  1063. this.updateTradeGoodID(parseInt(cityData.producedTradegood));
  1064. resourcesChanged = this.updateResource(Constant.Resources.WOOD, cityData.currentResources[Constant.ResourceIDs.WOOD], cityData.resourceProduction, 0) || resourcesChanged;
  1065. resourcesChanged = this.updateResource(Constant.Resources.WINE, cityData.currentResources[Constant.ResourceIDs.WINE], this.getTradeGoodID == Constant.ResourceIDs.WINE ? cityData.tradegoodProduction : 0, wineConsumption) || resourcesChanged;
  1066. resourcesChanged = this.updateResource(Constant.Resources.MARBLE, cityData.currentResources[Constant.ResourceIDs.MARBLE], this.getTradeGoodID == Constant.ResourceIDs.MARBLE ? cityData.tradegoodProduction : 0, 0) || resourcesChanged;
  1067. resourcesChanged = this.updateResource(Constant.Resources.GLASS, cityData.currentResources[Constant.ResourceIDs.GLASS], this.getTradeGoodID == Constant.ResourceIDs.GLASS ? cityData.tradegoodProduction : 0, 0) || resourcesChanged;
  1068. resourcesChanged = this.updateResource(Constant.Resources.SULFUR, cityData.currentResources[Constant.ResourceIDs.SULFUR], this.getTradeGoodID == Constant.ResourceIDs.SULFUR ? cityData.tradegoodProduction : 0, 0) || resourcesChanged;
  1069. this.knownTime = $.now();
  1070.  
  1071. var $actionPointElem = $('#js_GlobalMenu_maxActionPoints');
  1072. if(cityData.maxActionPoints) {
  1073. changes['actionPoints'] = this.updateActionPoints(cityData.maxActionPoints || 0)
  1074. } else {
  1075. changes['actionPoints'] = this.updateActionPoints(parseInt($actionPointElem.text()) || 0);
  1076. }
  1077. changes['coordinates'] = this.updateCoordinates(parseInt(cityData.islandXCoord), parseInt(cityData.islandYCoord));
  1078. if(ikariam.viewIsCity) {
  1079. changes['name'] = this.updateName(cityData.name);
  1080. changes['population'] = this.updatePopulation(cityData.currentResources['population']);
  1081. changes['islandId'] = this.updateIslandID(parseInt(cityData.islandId));
  1082. changes['coordinates'] = this.updateCoordinates(parseInt(cityData.islandXCoord), parseInt(cityData.islandYCoord));
  1083. }
  1084. if(ikariam.viewIsIsland) {
  1085. changes['islandId'] = this.updateIslandID(parseInt(cityData.id));
  1086. changes['coordinates'] = this.updateCoordinates(parseInt(cityData.xCoord), parseInt(cityData.yCoord));
  1087. }
  1088. changes['citizens'] = this.updateCitizens(cityData.currentResources['citizens']);
  1089. database.getGlobalData.addLocalisedString('cities', $('#js_GlobalMenu_cities').find('> span').text());
  1090. database.getGlobalData.addLocalisedString('ActionPoints', $actionPointElem.attr('title'));
  1091. if(cityData['gold']) {
  1092. database.getGlobalData.finance.currentGold = parseFloat(cityData['gold'])
  1093. }
  1094. } catch(e) {
  1095. SITR.error('fetchCurrentCityData', e)
  1096. } finally {
  1097. cityData = null
  1098. }
  1099. events(Constant.Events.CITY_UPDATED).pub(this.getId, changes);
  1100. if(resourcesChanged) {
  1101. events(Constant.Events.RESOURCES_UPDATED).pub(this.getId, resourcesChanged)
  1102. }
  1103. }
  1104. },
  1105. get getCorruption() {
  1106. if (typeof this._corruption != "function") {
  1107. this._corruption = Utils.cacheFunction(function () {
  1108. return Math.max(0, 1 - ((this.getBuildingFromName(Constant.Buildings.GOVERNORS_RESIDENCE) ? this.getBuildingFromName(Constant.Buildings.GOVERNORS_RESIDENCE).getLevel
  1109. : this.getBuildingFromName(Constant.Buildings.PALACE) ? this.getBuildingFromName(Constant.Buildings.PALACE).getLevel
  1110. : 0) + 1) / database.getCityCount + Constant.GovernmentData[database.getGlobalData.getGovernmentType].corruption);
  1111. }.bind(this), 1000);
  1112. }
  1113. return this._corruption();
  1114. },
  1115. get isCurrentCity() {
  1116. return this.getId == ikariam.CurrentCityId
  1117. },
  1118. getResource : function(name) {
  1119. return this._resources[name]
  1120. },
  1121. updateResource : function(resourceName, current, production, consumption) {
  1122. return this.getResource(resourceName).update(current, production, consumption)
  1123. },
  1124. get getIncome() {
  1125. return this._citizens * 3
  1126. },
  1127. updateIncome : function(value) {
  1128. if(Math.abs(this._citizens - value / 3) > 2) {
  1129. return this.updateCitizens((value / 3))
  1130. }
  1131. return false
  1132.  
  1133. },
  1134. get getExpenses() {
  1135. return -1 * this._research.getResearchCost
  1136. },
  1137. updateExpenses : function(value) {
  1138. return this._research.updateCost(Math.abs(value))
  1139. },
  1140. get getBuildings() {
  1141. return this._buildings
  1142. },
  1143. getBuildingsFromName : function(name) {
  1144. var ret = [];
  1145. var i = this._buildings.length;
  1146. while(i--) {
  1147. if(this._buildings[i].getName == name) ret.push(this._buildings[i])
  1148. }
  1149. return ret
  1150. },
  1151. getBuildingFromName : function(name) {
  1152. var i = this._buildings.length;
  1153. while(i--) {
  1154. if(this._buildings[i].getName == name)
  1155. return this._buildings[i];
  1156. }
  1157. return null
  1158. },
  1159. getBuildingFromPosition : function(position) {
  1160. return this._buildings[position]
  1161. },
  1162. get getTradeGood() {
  1163. for(var resourceName in Constant.ResourceIDs) {
  1164. if(this._tradeGoodID == Constant.ResourceIDs[resourceName]) {
  1165. return Constant.Resources[resourceName]
  1166. }
  1167. }
  1168. return null;
  1169. },
  1170. get getTradeGoodID() {
  1171. return this._tradeGoodID
  1172. },
  1173. updateTradeGoodID : function(value) {
  1174. var changed = this._tradeGoodID != value;
  1175. if(changed) {
  1176. this._tradeGoodID = value;
  1177. }
  1178. return changed
  1179. },
  1180. updatePriests : function(priests) { //TODO: tidy up
  1181. var changed = this._priests != priests;
  1182. this._priests = priests;
  1183. return changed;
  1184. },
  1185. get getName() {
  1186. return this._name
  1187. },
  1188. updateName : function(value) {
  1189. var changed = this._name != value;
  1190. if(changed) {
  1191. this._name = value;
  1192. }
  1193. return changed
  1194. },
  1195. get getId() {
  1196. return this._id
  1197. },
  1198. get research() {
  1199. return this._research
  1200. },
  1201. updateResearchers : function(value) {
  1202. return this._research.updateResearchers(value)
  1203. },
  1204. updateResearchCost : function(value) {
  1205. return this._research.updateCost(value)
  1206. },
  1207. get storageCapacity() {
  1208. return null
  1209. },
  1210. get getAvailableActions() {
  1211. return this._actionPoints
  1212. },
  1213. updateActionPoints : function(value) {
  1214. var changed = this._actionPoints != value;
  1215. this._actionPoints = value;
  1216. return changed
  1217. },
  1218. get getCoordinates() {
  1219. return (this._coordinates ? [this._coordinates.x, this._coordinates.y] : null)
  1220. },
  1221. updateCoordinates : function(x, y) {
  1222. this._coordinates = {x: x, y: y};
  1223. return false;
  1224. },
  1225. get getIslandID() {
  1226. return this._islandID
  1227. },
  1228. updateIslandID : function(id) {
  1229. this._islandID = id;
  1230. return false;
  1231. },
  1232. get getCulturalGoods() {
  1233. return this._culturalGoods
  1234. },
  1235. updateCulturalGoods : function(value) {
  1236. var changed = this._culturalGoods !== value;
  1237. if (changed) {
  1238. this._culturalGoods = value;
  1239. }
  1240. return changed
  1241. },
  1242. get getIncomingResources() {
  1243. return database.getGlobalData.getResourceMovementsToCity(this.getId)
  1244. },
  1245. get getIncomingMilitary() {
  1246. return database.getGlobalData.getMilitaryMovementsToCity(this.getId)
  1247. },
  1248. get _getMaxPopulation() {
  1249. var mPop = 0;
  1250. if(this.getBuildingFromName(Constant.Buildings.TOWN_HALL)) {
  1251. mPop = Math.floor((10 * Math.pow(this.getBuildingFromName(Constant.Buildings.TOWN_HALL).getLevel, 1.5))) * 2 + 40;
  1252. }
  1253. // Government bonus
  1254. if(database.getGlobalData.getResearchTopicLevel(Constant.Research.Science.WELL_CONSTRUCTION) && this.getBuildingFromName(Constant.Buildings.PALACE)) {
  1255. mPop += 50;
  1256. }
  1257. if(database.getGlobalData.getResearchTopicLevel(Constant.Research.Economy.UTOPIA) && this.getBuildingFromName(Constant.Buildings.PALACE)) {
  1258. mPop += 200
  1259. }
  1260. if(database.getGlobalData.getResearchTopicLevel(Constant.Research.Economy.HOLIDAY)) {
  1261. mPop += 50;
  1262. }
  1263. mPop += database.getGlobalData.getResearchTopicLevel(Constant.Research.Economy.ECONOMIC_FUTURE) * 20;
  1264. return mPop;
  1265. },
  1266. get military() {
  1267. return this._military
  1268. },
  1269. get getAvailableBuildings() {
  1270. var i = 16 + database.getGlobalData.getResearchTopicLevel(Constant.Research.Economy.BUREACRACY) + database.getGlobalData.getResearchTopicLevel(Constant.Research.Seafaring.PIRACY);
  1271. $.each(this.getBuildings, function(idx, building) {
  1272. i -= !building.isEmpty
  1273. }); //dec per populated spot
  1274. return i
  1275. },
  1276. get maxResourceCapacities() {
  1277. if(!this._capacities.invalid) {
  1278. return this._capacities
  1279. }
  1280.  
  1281. var ret = {};
  1282. ret[Constant.Buildings.DUMP] = {storage: 0, safe: 0};
  1283. ret[Constant.Buildings.WAREHOUSE] = {storage: 0, safe: 0};
  1284. ret[Constant.Buildings.TOWN_HALL] = {storage: 2500, safe: 100};
  1285. $.each(this.getBuildingsFromName(Constant.Buildings.WAREHOUSE), function(i, building) {
  1286. ret[Constant.Buildings.WAREHOUSE].storage += building.getLevel * 8000;
  1287. ret[Constant.Buildings.WAREHOUSE].safe += building.getLevel * 480;
  1288. });
  1289. $.each(this.getBuildingsFromName(Constant.Buildings.DUMP), function(i, building) {
  1290. ret[Constant.Buildings.DUMP].storage += building.getLevel * 32000
  1291. });
  1292.  
  1293. var capacity = 0;
  1294. var safe = 0;
  1295. for(var key in ret) {
  1296. capacity += ret[key].storage;
  1297. safe += ret[key].safe;
  1298. }
  1299. //TODO: Premium storage safety;
  1300. this._capacities = {
  1301. capacity : capacity * (1 + (database.getGlobalData.hasPremiumFeature(Constant.Premium.STORAGECAPACITY_BONUS) * Constant.PremiumData[Constant.Premium.STORAGECAPACITY_BONUS].bonus)),
  1302. safe : safe * (1 + (database.getGlobalData.hasPremiumFeature(Constant.Premium.SAFECAPACITY_BONUS) * Constant.PremiumData[Constant.Premium.SAFECAPACITY_BONUS].bonus)),
  1303. buildings: ret
  1304. };
  1305. return this._capacities;
  1306. },
  1307. get _getSatisfactionData() {
  1308. var r = {
  1309. city : 196,
  1310. museum : {
  1311. cultural: 0,
  1312. level : 0
  1313. },
  1314. government: 0,
  1315. tavern : {
  1316. wineConsumption: 0,
  1317. level : 0
  1318. },
  1319. research : 0,
  1320. priest : 0,
  1321. total : 0
  1322. };
  1323. if(this.getBuildingFromName(Constant.Buildings.MUSEUM)) {
  1324. r.museum.cultural = this.getCulturalGoods * 50;
  1325. r.museum.level = this.getBuildingFromName(Constant.Buildings.MUSEUM).getLevel * 20;
  1326. }
  1327. r.government = Constant.GovernmentData[database.getGlobalData.getGovernmentType].happiness
  1328. + (Constant.GovernmentData[database.getGlobalData.getGovernmentType].happinessWithoutTemple * (this.getBuildingFromName(Constant.Buildings.TEMPLE) == undefined));
  1329. if(this.getBuildingFromName(Constant.Buildings.TAVERN)) {
  1330. r.tavern.level = this.getBuildingFromName(Constant.Buildings.TAVERN).getLevel * 12;
  1331. var consumption = Math.floor(this.getResource(Constant.Resources.WINE).getConsumption * (100 / ( 100 - (this.getBuildingFromName(Constant.Buildings.VINEYARD) ? this.getBuildingFromName(Constant.Buildings.VINEYARD).getLevel : 0))));
  1332. for(var i = 0; i < Constant.BuildingData[Constant.Buildings.TAVERN].wineUse.length; i++) {
  1333. if(Math.abs(Constant.BuildingData[Constant.Buildings.TAVERN].wineUse[i] - consumption) <= 1) {
  1334. r.tavern.wineConsumption = 60 * i;
  1335. break
  1336. }
  1337. }
  1338. }
  1339. r.research = (25 * database.getGlobalData.getResearchTopicLevel(2080)) + (database.getGlobalData.getResearchTopicLevel(2999) * 10) + (this.getBuildingFromName(Constant.Buildings.PALACE) ? 50 * database.getGlobalData.getResearchTopicLevel(3010) : 0) + (this.getBuildingFromName(Constant.Buildings.PALACE) ? 200 * database.getGlobalData.getResearchTopicLevel(2120) : 0);
  1340.  
  1341. r.priest = this._priests * 500 / this._getMaxPopulation * Constant.GovernmentData[database.getGlobalData.getGovernmentType].happinessBonusWithTempleConversion;
  1342. r.priest = (r.priest <= 150 ? r.priest : 150);
  1343.  
  1344. r.city = 196;
  1345. var total = 0;
  1346. for(var n in r) {
  1347. if(typeof r[n] === 'object') {
  1348. for(var o in r[n]) {
  1349. total += r[n][o];
  1350. }
  1351. } else {
  1352. total += r[n];
  1353. }
  1354. }
  1355. r.total = total;
  1356. r.corruption = Math.round(this._population + this._pop.happiness -total);
  1357. return r
  1358. },
  1359. updatePopulation : function(population) {
  1360. var changed = this._population != population;
  1361. this._population = population;
  1362. this._lastPopUpdate = $.now();
  1363. return changed;
  1364. },
  1365. updateCitizens : function(citizens) {
  1366. var changed = this._citizens != citizens;
  1367. this._citizens = citizens;
  1368. this._lastPopUpdate = $.now();
  1369. return changed;
  1370. },
  1371. projectPopData : function(untilTime) {
  1372. var plus = this._getSatisfactionData;
  1373. var maxPopulation = this._getMaxPopulation;
  1374. var happiness = (1 - this.getCorruption) * plus.total - this._population;
  1375. var hours = ((untilTime - this._lastPopUpdate) / 3600000);
  1376. var pop = this._population + happiness * (1 - Math.pow(Math.E, -(hours / 50)));
  1377. pop = (pop > maxPopulation) ? this._population > maxPopulation ? this._population : maxPopulation : pop;
  1378. happiness = (1 - this.getCorruption) * plus.total - pop;
  1379. // this.updateCitizens(this._citizens + pop-this._population)
  1380. // this.updatePopulation(pop)
  1381. this._citizens = this._citizens + pop - this._population;
  1382. this._population = pop;
  1383. this._lastPopUpdate = untilTime;
  1384. var old = $.extend({}, this._pop);
  1385. this._pop = {currentPop: pop, maxPop: maxPopulation, satisfaction: plus, happiness: happiness, growth: happiness * 0.02};
  1386. if(Math.floor(old.currentPop) != Math.floor(this._pop.currentPop) || Math.floor(old.maxPop) != Math.floor(this._pop.maxPop) || Math.floor(old.happiness) != Math.floor(this._pop.happiness)) {
  1387. events(Constant.Events.CITY_UPDATED).pub(this.getId, {population: true});
  1388. }
  1389. },
  1390. get populationData() {
  1391. return this._pop;
  1392. },
  1393. processUnitBuildList : function() {
  1394. var newList = [];
  1395. for(var i = 0; i < this.unitBuildList.length; i++) {
  1396. var list = this.unitBuildList[i];
  1397. if(list.completionTime <= $.now()) {
  1398. for(var uID in list.units) {
  1399. var j = this.army.length;
  1400. }
  1401. while(j) {
  1402. j--;
  1403. if(uID == this.army[j].id) {
  1404. this.army[uID] += list.units[uID]
  1405. }
  1406. }
  1407. } else {
  1408. newList.push(list);
  1409. }
  1410. }
  1411. this.unitBuildList = newList;
  1412. },
  1413. clearUnitBuildList : function(type) {
  1414. if(type) {
  1415. var newList = [];
  1416. for(var i = 0; i < this.unitBuildList.length; i++) {
  1417. if(this.unitBuildList[i].type != type) {
  1418. newList.push(this.unitBuildList[i]);
  1419. }
  1420. }
  1421. }
  1422. this.unitBuildList = newList;
  1423. },
  1424. getUnitBuildsByUnit : function() {
  1425. var ret = {};
  1426. for(var i = 0; i < this.unitBuildList.length; i++) {
  1427. for(var uID in this.unitBuildList[i].units) {
  1428. ret[uID] = ret[uID] || [];
  1429. ret[uID].push({
  1430. count : this.unitBuildList[i].units[uID],
  1431. completionTime: this.unitBuildList[i].completionTime})
  1432. }
  1433. }
  1434. return ret;
  1435. },
  1436. getUnitTransportsByUnit : function() {
  1437. var ret = {};
  1438. var data = database.getGlobalData.militaryMovements[this.getId];
  1439. if(data) {
  1440. for(var row in data) {
  1441. for(var uID in data[row].troops) {
  1442. ret[uID] = ret[uID] || [];
  1443. ret[uID].push({
  1444. count : data[row].troops[uID],
  1445. arrivalTime: data[row].arrivalTime,
  1446. origin : data[row].originCityId})
  1447. }
  1448. }
  1449. }
  1450. return ret;
  1451. },
  1452. get isCapital() {
  1453. return this.getBuildingFromName(Constant.Buildings.PALACE) !== null
  1454. },
  1455. get isColony() {
  1456. return this.getBuildingFromName(Constant.Buildings.PALACE) === null
  1457. },
  1458. get isUpgrading() {
  1459. var res = false;
  1460. $.each(this.getBuildings, function (idx, building) {
  1461. res = res || building.isUpgrading;
  1462. });
  1463. return res
  1464. }
  1465. };
  1466. function GlobalData() {
  1467. this._version = {
  1468. lastUpdateCheck : 0,
  1469. latestVersion : null,
  1470. installedVersion: 0
  1471. };
  1472. this._research = {
  1473. topics : {},
  1474. lastUpdate: 0
  1475. };
  1476. this.governmentType = 'demokratie';
  1477. this.fleetMovements = [];
  1478. this.militaryMovements = [];
  1479. this.finance = {
  1480. armyCost : 0,
  1481. armySupply : 0,
  1482. fleetCost : 0,
  1483. fleetSupply : 0,
  1484. currentGold : 0,
  1485. sigmaExpenses: function() {
  1486. return this.armyCost + this.armySupply + this.fleetCost + this.fleetSupply
  1487. },
  1488. sigmaIncome : 0,
  1489. lastUpdated : 0
  1490. };
  1491. this.localStrings = {};
  1492. this.premium = {}
  1493. }
  1494.  
  1495. GlobalData.prototype = {
  1496. init : function() {
  1497. $.each(Constant.Localization.default, this.addLocalisedString.bind(this));
  1498. $.each(this.fleetMovements, function(key, movement) {
  1499. this.fleetMovements[key] = new Movement(movement);
  1500. this.fleetMovements[key]._updateTimer = null;
  1501. this.fleetMovements[key].startUpdateTimer();
  1502. }.bind(this));
  1503. },
  1504. hasPremiumFeature: function(feature){
  1505. return this.premium[feature]?this.premium[feature].endTime > $.now() || this.premium[feature].continuous:false
  1506. },
  1507. setPremiumFeature:function(feature, endTime, continuous){
  1508. var ret = !this.hasPremiumFeature(feature) && endTime > $.now();
  1509. this.premium[feature] = {endTime:endTime, continuous:continuous};
  1510. return ret
  1511. },
  1512. getPremiumTimeRemaining :function(feature){
  1513. return this.premium[feature]?this.premium[feature].endTime > $.now():0;
  1514. },
  1515. getPremiumTimeContinuous :function(feature){
  1516. return this.premium[feature]?this.premium[feature].continuous:false
  1517. },
  1518. removeFleetMovement : function(id) {
  1519. var index = -1;
  1520. $.each(this.fleetMovements, function(i, movement) {
  1521. if(movement.getId == id) {
  1522. this.fleetMovements.splice(i, 1);
  1523. return false;
  1524. }
  1525. }.bind(this))
  1526. },
  1527. addFleetMovement : function(transport) {
  1528. try {
  1529. this.fleetMovements.push(transport);
  1530. transport.startUpdateTimer();
  1531. this.fleetMovements.sort(function(a, b) {
  1532. return a.getArrivalTime - b.getArrivalTime
  1533. });
  1534. var changes = [];
  1535.  
  1536. $.each(transport.getResources, function(resourceName, value) {
  1537. changes.push(resourceName)
  1538. });
  1539. //Todo: implement drilled down resource changes
  1540. return changes
  1541. } catch(e) {
  1542. SITR.error('addFleetMovement', e);
  1543. }
  1544. },
  1545. getMovementById : function(id) {
  1546. for(var i in this.fleetMovements) {
  1547. if(this.fleetMovements[i].getId == id) {
  1548. return this.fleetMovements[i]
  1549. }
  1550. }
  1551. return false;
  1552. },
  1553. clearFleetMovements : function() {
  1554. var changes = [];
  1555. $.each(this.fleetMovements, function(index, item) {
  1556. changes.push(item.getTargetCityId);
  1557. item.clearUpdateTimer();
  1558. });
  1559. this.fleetMovements.length = 0;
  1560. return $.exclusive(changes)
  1561. },
  1562. getResourceMovementsToCity : function(cityID) {
  1563. return this.fleetMovements.filter(function(el) {
  1564. if(el.getTargetCityId == cityID) {
  1565. return (el.getMission == 'trade' || el.getMission == 'transport')
  1566. }
  1567. });
  1568. },
  1569. getMilitaryMovementsToCity: function(cityID) {
  1570. return this.fleetMovements.filter(function(el) {
  1571. if(el.getTargetCityId == cityID) {
  1572. return (el.getMission != 'trade' && el.getMission != 'transport')
  1573. }
  1574. });
  1575. },
  1576. getResearchTopicLevel : function(research) {
  1577. return this._research.topics[research] || 0;
  1578. },
  1579. updateResearchTopic : function(topic, level) {
  1580. var changed = this.getResearchTopicLevel(topic) != level;
  1581. this._research.topics[topic] = level;
  1582. return changed;
  1583. },
  1584. get getGovernmentType() {
  1585. return this.governmentType
  1586. },
  1587. getLocalisedString : function(string) {
  1588. var lString;
  1589. //normal building var names "townHall"
  1590. lString = this.localStrings[string.replace(/([A-Z])/g, "_$1").toLowerCase()];
  1591. //space in name "town Hall"
  1592. if(lString == undefined)
  1593. lString = this.localStrings[string.toLowerCase().split(' ').join('_')];
  1594. return (lString == undefined) ? string : lString;
  1595. },
  1596. addLocalisedString : function(string, value) {
  1597. if(this.getLocalisedString(string) == string)
  1598. this.localStrings[string.toLowerCase().split(' ').join('_')] = value;
  1599. },
  1600. isOldVersion : function() {
  1601. return this._version.latestVersion < this._version.installedVersion;
  1602.  
  1603. }
  1604. };
  1605. function Setting(name) {
  1606. this._name = name;
  1607. this._value = null
  1608. }
  1609. Setting.prototype = {
  1610. get name() {
  1611. return database.getGlobalData.getLocalisedString(this._name);
  1612. },
  1613. get type() {
  1614. return Constant.SettingData[this._name].type
  1615. },
  1616. get description() {
  1617. return database.getGlobalData.getLocalisedString(this._name + '_description');
  1618. },
  1619. get value() {
  1620. return (this._value!=null?this._value:Constant.SettingData[this._name].default)
  1621. },
  1622. get category() {
  1623. return Constant.SettingData[this._name].category
  1624. },
  1625. get choices() {
  1626. return Constant.SettingData[this._name].choices || false
  1627. },
  1628. set value(value) {
  1629. if (this.type === 'boolean') {
  1630. this._value = !!value;
  1631. }
  1632. else if (this.type === 'number') {
  1633. if (!isNaN(value)) {
  1634. this._value = value
  1635. }
  1636. }
  1637. else if (this.type === 'array' || this.type === 'orderedList') {
  1638. if (Object.prototype.toString.call(value) === '[object Array]') {
  1639. this._value = value
  1640. }
  1641. }
  1642. },
  1643. toJSON:function () {
  1644. return {value:this._value}
  1645. }};
  1646. /***********************************************************************************************************************
  1647. * SITR
  1648. **********************************************************************************************************************/
  1649. var SITR = {
  1650. version : 1.214,
  1651. scriptId : 132578,
  1652. scriptName : 'Simple Ikariam Town Resources Board',
  1653. logger : null,
  1654. loaded : false,
  1655. log : function(val) {
  1656. if(debug) console.log('SITR: ', $.makeArray(arguments));
  1657. if(log) {
  1658. if(this.logger) {
  1659. this.logger.val(val + '\n' + this.logger.val());
  1660. return true
  1661. } else {
  1662. render.$tabs.append($(document.createElement("div")).attr('id', 'SITR_Log'));
  1663. $('#SITR_Log').html('<div><textarea id="SITR_Logbox" rows="20" cols="120"></textarea></div>');
  1664. $('<li><a href="#SITR_Log"><img class="ui-icon ui-icon-info"/></a></li>').appendTo("#SITR_Tabs .ui-tabs-nav");
  1665. render.$tabs.tabs('refresh');
  1666. this.logger = $('#SITR_Logbox');
  1667. return this.log(val)
  1668. }
  1669. }
  1670. },
  1671. error : function(func, e) {
  1672. this.log('****** Error raised in ' + func + ' ******');
  1673. this.log(e.name + ' : ' + e.message);
  1674. this.log(e.stack);
  1675. this.log('****** End ******');
  1676. if(debug) {
  1677. console.error('****** Error raised in ' + func + ' ******');
  1678. console.error(e.name + ' : ' + e.message);
  1679. console.error(e.stack);
  1680. console.error('****** End ******')
  1681. }
  1682. },
  1683. time : function(func, name){
  1684. timing && console.time(name);
  1685. var ret = func();
  1686. timing && console.timeEnd(name);
  1687. return ret
  1688. },
  1689. Init : function() {
  1690. ikariam.Init();
  1691. render.Init();
  1692. database.Init(ikariam.Host());
  1693. this.CheckForUpdates(false);
  1694. GM_registerMenuCommand(this.scriptName + ' - Manual Update', function() {
  1695. SITR.CheckForUpdates(true);
  1696. });
  1697.  
  1698. },
  1699. //original snippet taken from http://userscripts.org/scripts/show/20145
  1700. CheckForUpdates: function(forced) {
  1701. if((forced) || ((database.getGlobalData.LastUpdateCheck + 86400000 <= $.now()) && database.settings.autoUpdates.value)) // Checks once a day (24 h * 60 m * 60 s * 1000 ms)
  1702. {
  1703. try {
  1704. GM_xmlhttpRequest({
  1705. method : 'GET',
  1706. url : 'http://userscripts.org/scripts/source/' + SITR.scriptId + '.meta.js?' + $.now(),
  1707. headers: {'Cache-Control': 'no-cache'},
  1708. onload : function(resp) {
  1709. var remote_version, rt;
  1710. rt = resp.responseText;
  1711. database.getGlobalData.LastUpdateCheck = $.now();
  1712. remote_version = parseFloat(/@version\s*(.*?)\s*$/m.exec(rt)[1]);
  1713. if(SITR.version != -1) {
  1714. if(remote_version > SITR.version) {
  1715. if(confirm('There is an update available for the Greasemonkey script "' + SITR.scriptName + '."\nWould you like to go to the install page now?')) {
  1716. GM_openInTab('http://userscripts.org/scripts/show/' + SITR.scriptId);
  1717. }
  1718. } else if(forced)
  1719. render.toast('No update is available for "' + SITR.scriptName + '."');
  1720. }
  1721. database.getGlobalData.latestVersion = remote_version;
  1722. }
  1723. });
  1724. } catch(err) {
  1725. if(forced)
  1726. render.toast('An error occurred while checking for updates:\n' + err);
  1727. }
  1728. }
  1729. },
  1730. HardReset : function() {
  1731. database = {};
  1732. SITR.deleteVar("settings");
  1733. SITR.deleteVar("Options"); //legacy
  1734. SITR.deleteVar("options"); //legacy
  1735. SITR.deleteVar("cities");
  1736. SITR.deleteVar("LocalStrings");
  1737. SITR.deleteVar("globalData");
  1738. render.toast('Data Reset, reloading the page in a few seconds');
  1739. setTimeout(function() {
  1740. document.location = document.getElementById('js_cityLink').children[0].href
  1741. }, 3500);
  1742. },
  1743. setVar : function(varname, varvalue) {
  1744. GM_setValue(ikariam.Host() + varname, varvalue);
  1745. },
  1746. deleteVar : function(varname) {
  1747. GM_deleteValue(ikariam.Host() + varname);
  1748. },
  1749. getVar : function(varname, vardefault) {
  1750. var ret = GM_getValue(ikariam.Host() + varname);
  1751. if(ret == undefined) {
  1752. return vardefault;
  1753. }
  1754. return ret;
  1755. }
  1756. };
  1757. /***********************************************************************************************************************
  1758. * database
  1759. **********************************************************************************************************************/
  1760. var database = {
  1761. _globalData : new GlobalData(),
  1762. cities : {},
  1763. settings : {
  1764. version : SITR.version,
  1765. window : {
  1766. left : 150,
  1767. top : 180,
  1768. activeTab: 0,
  1769. visible : true
  1770. },
  1771. addOptions : function(objVals) {
  1772. return $.mergeValues(this, objVals);
  1773. }
  1774. },
  1775. Init : function(host) {
  1776. $.each(Constant.Settings, function(key, value){
  1777. this.settings[value] = new Setting(value);
  1778. }.bind(database))
  1779. var prefix = host;
  1780. prefix = prefix.replace('.ikariam.', '-');
  1781. prefix = prefix.replace('.', '-');
  1782. this.Prefix = prefix;
  1783. this.Load();
  1784. events(Constant.Events.LOCAL_STRINGS_AVAILABLE).sub(ikariam.getLocalizationStrings.bind(this));
  1785. $(window).on("beforeunload", function() {
  1786. setTimeout(function() {
  1787. database.Save();
  1788. }, 0);
  1789. });
  1790. },
  1791. addCity : function(id, a) {
  1792. if(a) {
  1793. return $.mergeValues(new City(id), a);
  1794. } else return new City(id);
  1795. },
  1796. get getBuildingCounts() {
  1797. var buildingCounts = {};
  1798. $.each(this.cities, function(cityId, city) {
  1799. $.each(Constant.Buildings, function(key, value) {
  1800. if(database.settings.compressedBuildingList.value && (value == Constant.Buildings.WINERY || value == Constant.Buildings.STONEMASON || value == Constant.Buildings.GLASSBLOWER || value == Constant.Buildings.ALCHEMISTS_TOWER)) {
  1801. buildingCounts['productionBuilding'] = Math.max(buildingCounts['productionBuilding'] || 0, city.getBuildingsFromName(value).length)
  1802. } else if(database.settings.compressedBuildingList.value && (value == Constant.Buildings.GOVERNORS_RESIDENCE || value == Constant.Buildings.PALACE)) {
  1803. buildingCounts['colonyBuilding'] = Math.max(buildingCounts['colonyBuilding'] || 0, city.getBuildingsFromName(value).length)
  1804. } else {
  1805. buildingCounts[value] = Math.max(buildingCounts[value] || 0, city.getBuildingsFromName(value).length)
  1806. }
  1807. })
  1808. });
  1809. return buildingCounts
  1810. },
  1811. startMonitoringChanges: function() {
  1812. //events('cityChanged').sub(this.cityChange.bind(this));
  1813. events(Constant.Events.BUILDINGS_UPDATED).sub(this.Save.bind(this));
  1814. events(Constant.Events.GLOBAL_UPDATED).sub(this.Save.bind(this));
  1815. events(Constant.Events.MOVEMENTS_UPDATED).sub(this.Save.bind(this));
  1816. events(Constant.Events.RESOURCES_UPDATED).sub(this.Save.bind(this));
  1817. //events(Constant.Events.CITY_UPDATED).sub(this.Save.bind(this));
  1818. events(Constant.Events.MILITARY_UPDATED).sub(this.Save.bind(this));
  1819. events(Constant.Events.PREMIUM_UPDATED).sub(this.Save.bind(this));
  1820. },
  1821. Load : function() {
  1822. var settings = this.UnSerialize(SITR.getVar("settings", ""));
  1823. if(typeof settings === 'object') {
  1824. if(!this.isDatabaseOutdated(settings.version)) {
  1825.  
  1826. $.mergeValues(this.settings, settings);
  1827.  
  1828. var globalData = this.UnSerialize(SITR.getVar("globalData", ""));
  1829. if (globalData.governmentType == '') globalData.governmentType = 'demokratie';
  1830. if(typeof globalData == 'object') {
  1831. $.mergeValues(this._globalData, globalData);
  1832.  
  1833. }
  1834. var cities = this.UnSerialize(SITR.getVar("cities", ""));
  1835. if(typeof cities == 'object') {
  1836. for(var cityID in cities) {
  1837. (this.cities[cityID] = this.addCity(cities[cityID]._id, cities[cityID])).init()
  1838. }
  1839. }
  1840. }
  1841. this._globalData.init();
  1842. }
  1843. events(Constant.Events.DATABASE_LOADED).pub();
  1844. },
  1845. Serialize : function(data) {
  1846. if(data)
  1847. try {
  1848. var ret = JSON.stringify(data)
  1849. } catch(e) {
  1850. SITR.log('error saving')
  1851. }
  1852. return ret || undefined;
  1853. },
  1854. UnSerialize : function(data) {
  1855. if(data)
  1856. try {
  1857. var ret = JSON.parse(data)
  1858. } catch(e) {
  1859. SITR.log('error loading')
  1860. }
  1861. return ret || undefined;
  1862. },
  1863. Save : function() {
  1864. events.scheduleAction(function() {
  1865. SITR.setVar("cities", database.Serialize(database.cities));
  1866. SITR.setVar("settings", database.Serialize(database.settings));
  1867. SITR.setVar("globalData", database.Serialize(database._globalData));
  1868. })
  1869.  
  1870. },
  1871. get getGlobalData() {
  1872. return this._globalData
  1873. },
  1874. isDatabaseOutdated : function(version) {
  1875. return 1.209 > (version || 0);
  1876. },
  1877. getCityFromId : function(id) {
  1878. return this.cities[id] || null
  1879. },
  1880. get getArmyTotals() {
  1881. if(!this._armyTotals) {
  1882. this._armyTotals = Utils.cacheFunction(this._getArmyTotals.bind(database), 1000)
  1883. }
  1884. return this._armyTotals()
  1885. },
  1886. _getArmyTotals: function() {
  1887. var totals = {};
  1888. $.each(Constant.UnitData, function(unitId, info) {
  1889. totals[unitId] = {training: 0, total: 0, incoming: 0};
  1890. });
  1891. $.each(this.cities, function(cityId, city) {
  1892. var train = city.military.getTrainingTotals;
  1893. var incoming = city.military.getIncomingTotals;
  1894. var total = city.military.getUnits.totals;
  1895. $.each(Constant.UnitData, function(unitId, info) {
  1896. totals[unitId].training += train[unitId] || 0;
  1897. totals[unitId].total += total[unitId] || 0;
  1898. totals[unitId].incoming += incoming[unitId] || 0;
  1899. });
  1900. });
  1901. return totals
  1902. },
  1903. get getCityCount (){
  1904. return Object.keys(this.cities).length
  1905. },
  1906. _getArmyTrainingTotals :function(){
  1907.  
  1908. }
  1909. };
  1910. /***********************************************************************************************************************
  1911. * render view
  1912. **********************************************************************************************************************/
  1913.  
  1914. var render = {
  1915. mainContentBox : null,
  1916. $tabs : null,
  1917. cityRows : {
  1918. building: {},
  1919. resource: {},
  1920. army : {}
  1921. },
  1922. _cssResLoaded : false,
  1923. toolTip : {
  1924. elem : null,
  1925. timer: null,
  1926. hide : function() {
  1927. render.toolTip.elem.parent().hide()
  1928. },
  1929. show : function() {
  1930. render.toolTip.elem.parent().show()
  1931. },
  1932.  
  1933. mouseOver : function(event) {
  1934. if(render.toolTip.timer) {
  1935. render.toolTip.timer()
  1936. }
  1937. var f = function(shiftKey) {
  1938. return function() {
  1939. var elem;
  1940. elem = $(event.target).attr('data-tooltip') ? event.target : $(event.target).parents('[data-tooltip]');
  1941.  
  1942. render.toolTip.elem.html(render.toolTip.dynamicTip($(event.target).parents('tr').attr('id') ? $(event.target).parents('tr').attr('id').split('_').pop() : 0, elem));
  1943. return render.toolTip.elem.html()
  1944. }
  1945. }(event.originalEvent.shiftKey);
  1946. if(f(event.originalEvent.shiftKey)) {
  1947. render.toolTip.show();
  1948. render.toolTip.timer = events.scheduleActionAtInterval(f, 1000);
  1949. }
  1950. },
  1951. mouseMove : function(event) {
  1952. if(render.toolTip.timer && render.toolTip.elem) {
  1953. var l = parseInt(render.mainContentBox.css('left').split('px')[0]);
  1954. var t = parseInt(render.mainContentBox.css('top').split('px')[0]);
  1955. var x = event.pageX - 15 - l;
  1956. var y = event.pageY + 15 - t;
  1957.  
  1958. if(render.mainContentBox.height() - render.toolTip.elem.height() < y) {
  1959. y = event.pageY - render.toolTip.elem.height() - 15 - t
  1960. }
  1961. if(render.mainContentBox.width() - render.toolTip.elem.width() < x) {
  1962. x = event.pageX - render.toolTip.elem.width() + 15 - l
  1963. }
  1964. render.toolTip.elem.parent().css({
  1965. left: (x) + 'px',
  1966. top : (y) + 'px'
  1967. });
  1968. }
  1969. },
  1970. mouseOut : function(event) {
  1971. if(render.toolTip.timer) {
  1972. render.toolTip.timer();
  1973. render.toolTip.timer = null
  1974. }
  1975. render.toolTip.hide()
  1976. },
  1977. init : function() {
  1978. render.toolTip.elem = render.mainContentBox.append($('<div id="SITRTip" style="z-index: 999999999;"><div class="content"></div></div>')).find('div.content');
  1979. render.mainContentBox.on('mouseover', '[data-tooltip]', render.toolTip.mouseOver).on('mousemove', '[data-tooltip]', render.toolTip.mouseMove).on('mouseout', '[data-tooltip]', render.toolTip.mouseOut);
  1980. },
  1981. dynamicTip: function(id, elem) {
  1982. var $elem = $(elem);
  1983. if($elem.attr('data-tooltip') === "dynamic") {
  1984. var tiptype = $elem.attr('class').split(" ")
  1985. } else {
  1986. return $elem.attr('data-tooltip') || '';
  1987. }
  1988. var city = database.getCityFromId(id);
  1989. var resourceName;
  1990. if(city) {
  1991. resourceName = $elem.is('td') ? $elem.attr('class').split(' ').pop() : $elem.parent('td').attr('class').split(' ').pop()
  1992. }
  1993. var total;
  1994. switch(tiptype.shift()) {
  1995. case "incoming":
  1996. return getIncomingTip();
  1997. break;
  1998. case "current":
  1999. return '';
  2000. break;
  2001. case "progressbar":
  2002. return getProgressTip();
  2003. break;
  2004. case "total":
  2005. switch($elem.attr('id').split('_').pop()) {
  2006. case "sigma":
  2007. return getResourceTotalTip();
  2008. break;
  2009. case "goldincome":
  2010. return getGoldIncomeTip();
  2011. break;
  2012. case "research":
  2013. var researchDat;
  2014. $.each(database.cities, function(cityId, city) {
  2015. if (researchDat){
  2016. $.each(city.research.researchData,function(key, value){
  2017. researchDat[key] += value;
  2018. })
  2019. }
  2020. else researchDat = $.extend({}, city.research.researchData);
  2021. });
  2022. return getResearchTip(researchDat);
  2023. break;
  2024. case "army":
  2025. return "soon";
  2026. break;
  2027. case "wineincome":
  2028. total = 0;
  2029. var consumption = 0;
  2030. resourceName = $elem.attr('id').split('_').pop().split('income').shift();
  2031. $.each(database.cities, function(cityId, c) {
  2032. total += c.getResource(resourceName).getProduction;
  2033. consumption += c.getResource(resourceName).getConsumption;
  2034. });
  2035.  
  2036. return getProductionConsumptionSubSumTip(total * 3600, consumption, true);
  2037. break;
  2038. default :
  2039. total = 0;
  2040. resourceName = $elem.attr('id').split('_').pop().split('income').shift();
  2041. $.each(database.cities, function(cityId, c) {
  2042. total += c.getResource(resourceName).getProduction
  2043. });
  2044. return getProductionTip(total * 3600);
  2045. break;
  2046. }
  2047. case "population":
  2048. return getPopulationTip();
  2049. break;
  2050. case "population_growth":
  2051. return getGrowthTip();
  2052. break;
  2053. case "research":
  2054. return getResearchTip();
  2055. break;
  2056. case "prodconssubsum":
  2057. return getProductionConsumptionSubSumTip(city.getResource(resourceName).getProduction * 3600, city.getResource(resourceName).getConsumption);
  2058. break;
  2059. case "building":
  2060. var bName = tiptype.shift(); //building name
  2061. var index = parseInt(bName.slice(-1)); //building level
  2062. bName = bName.slice(0, -1);
  2063. return getBuildingTooltip(city.getBuildingsFromName(bName)[index]);
  2064. case "army":
  2065. switch(tiptype.shift()) {
  2066. case "unit":
  2067. return '';
  2068. break;
  2069. case "movement":
  2070. return getArmyMovementTip(tiptype.pop());
  2071. break
  2072.  
  2073. }
  2074. break;
  2075. default :
  2076. return "";
  2077. break;
  2078. }
  2079. function getGoldIncomeTip() {
  2080. var researchCost = 0;
  2081. var income = 0;
  2082. $.each(database.cities, function(cityID, city) {
  2083. researchCost += Math.floor(city.getExpenses);
  2084. income += Math.floor(city.getIncome)
  2085. });
  2086. var expense = database.getGlobalData.finance.armyCost + database.getGlobalData.finance.armySupply + database.getGlobalData.finance.fleetCost + database.getGlobalData.finance.fleetSupply - researchCost;
  2087.  
  2088. return '<table>\n <thead>\n <td><img src="skin/resources/icon_gold.png" style="height: 11px;"></td>\n <td><b>Hour</b></td>\n <td class="lfdash"><b>Day</b></td>\n <td class="lfdash"><b>Week</b></td>\n <td></td>\n </thead>\n <tbody>\n <tr class="data">\n <td><b>-</b></td>\n <td> ' + Utils.FormatNumToStr(database.getGlobalData.finance.armyCost, false, 0) + ' </td>\n <td class="lfdash"> ' + Utils.FormatNumToStr(database.getGlobalData.finance.armyCost * 24, false, 0) + '</td>\n <td class="lfdash"> ' + Utils.FormatNumToStr(database.getGlobalData.finance.armyCost * 24 * 7, false, 0) + '</td>\n <td class="left lfdash"><i>«Army Cost</i></td>\n </tr>\n <tr class="data">\n <td><b>-</b></td>\n <td class="nolf"> ' + Utils.FormatNumToStr(database.getGlobalData.finance.fleetCost, false, 0) + '</td>\n <td class="lfdash">' + Utils.FormatNumToStr(database.getGlobalData.finance.fleetCost * 24, false, 0) + '</td>\n <td class="lfdash">' + Utils.FormatNumToStr(database.getGlobalData.finance.fleetCost * 24 * 7, false, 0) + '</td>\n <td class="left lfdash"><i>«Fleet Cost</i></td>\n </tr>\n <tr class="data">\n <td><b>-</b></td>\n <td class="nolf">' + Utils.FormatNumToStr(database.getGlobalData.finance.armySupply, false, 0) + '</td>\n <td class="lfdash">' + Utils.FormatNumToStr(database.getGlobalData.finance.armySupply * 24, false, 0) + '</td>\n <td class="lfdash">' + Utils.FormatNumToStr(database.getGlobalData.finance.armySupply * 24 * 7, false, 0) + '</td>\n <td class="left lfdash"><i>«Army Supply</i></td>\n </tr>\n <tr class="data">\n <td><b>-</b></td>\n <td class="nolf">' + Utils.FormatNumToStr(database.getGlobalData.finance.fleetSupply, false, 0) + '</td>\n <td class="lfdash">' + Utils.FormatNumToStr(database.getGlobalData.finance.fleetSupply * 24, false, 0) + '</td>\n <td class="lfdash">' + Utils.FormatNumToStr(database.getGlobalData.finance.fleetSupply * 24 * 7, false, 0) + '</td>\n <td class="left lfdash"><i>«Fleet Supply</i></td>\n </tr>\n <tr class="data">\n <td><b>-</b></td>\n <td class="nolf">' + Utils.FormatNumToStr(researchCost, false, 0) + '</td>\n <td class="lfdash">' + Utils.FormatNumToStr(researchCost * 24, false, 0) + '</td>\n <td class="lfdash">' + Utils.FormatNumToStr(researchCost * 24 * 7, false, 0) + '</td>\n <td class="left lfdash"><i>«Research</i></td>\n </tr>\n </tbody>\n <tfoot>\n <tr>\n <td class="icon incomeIcon"></td>\n <td class="nolf">' + Utils.FormatNumToStr(income, false, 0) + '</td>\n <td class="lfdash">' + Utils.FormatNumToStr(income * 24, false, 0) + '</td>\n <td class="lfdash">' + Utils.FormatNumToStr(income * 7 * 24, false, 0) + '</td>\n <td class="left lfdash"><i>«Income</i></td>\n </tr>\n <tr>\n <td><b>-</b></td>\n <td class="nolf">' + Utils.FormatNumToStr(expense, false, 0) + '</td>\n <td>' + Utils.FormatNumToStr(expense * 24, false, 0) + '</td>\n <td class="lfdash">' + Utils.FormatNumToStr(expense * 24 * 7, false, 0) + '</td>\n <td class="left lfdash"><i>«Expenses</i></td>\n </tr>\n <tr class="total">\n <td><b>Σ ' + ((income - expense > 0) ? '+' : '-') + '</b></td>\n <td class="lfdash">' + Utils.FormatNumToStr((income - expense), false, 0) + '</td>\n <td class="lfdash">' + Utils.FormatNumToStr((income - expense) * 24, false, 0) + '</td>\n <td class="lfdash">' + Utils.FormatNumToStr((income - expense) * 7 * 24, false, 0) + '</td>\n <td></td>\n </tr>\n </tfoot>\n</table>'
  2089. }
  2090.  
  2091. function getArmyMovementTip(unit) {
  2092. var total = 0;
  2093. var table = '<table>\n <thead>\n <td><img src="{0}" style="height: 11px;"></td>\n <td><b>Training</b></td>\n <td></td>\n </thead>\n <tbody>\n{1}\n <tr class="small">\n <td></td>\n <td>{2}</td>\n <td class="left"><i>«Total</i></td>\n </tr>\n </tbody>\n</table>';
  2094. var rows = '';
  2095. $.each(city.military.getTrainingForUnit(unit), function(index, data) {
  2096. rows += Utils.format('<tr class="data">\n <td><b>+</b></td>\n <td >{0}</td>\n <td ><i>«{1}</i></td>\n</tr>', [data.count, Utils.FormatTimeLengthToStr(data.time - $.now(), 3)]);
  2097. total += data.count;
  2098. });
  2099.  
  2100. if(rows === '') {
  2101. return ''
  2102. } else {
  2103. return Utils.format(table, [getImage(unit), rows, total])
  2104. }
  2105. }
  2106.  
  2107. function makeIncomeTooltip(income, icon) {
  2108. //income = income || 0;
  2109. switch(icon) {
  2110. case Constant.Resources.WOOD:
  2111. icon = 'skin/resources/icon_wood.png';
  2112. break;
  2113. case Constant.Resources.WINE:
  2114. icon = 'skin/resources/icon_wine.png';
  2115. break;
  2116. case Constant.Resources.MARBLE:
  2117. icon = 'skin/resources/icon_marble.png';
  2118. break;
  2119. case Constant.Resources.GLASS:
  2120. icon = 'skin/resources/icon_glass.png';
  2121. break;
  2122. case Constant.Resources.SULFUR:
  2123. icon = 'skin/resources/icon_sulfur.png';
  2124. break;
  2125. case 'research':
  2126. icon = 'skin/layout/bulb-on.png';
  2127. break;
  2128. case 'gold':
  2129. icon = 'skin/resources/icon_gold.png';
  2130. break;
  2131. default:
  2132. icon = '';
  2133. }
  2134. return '<table><thead><td><img src="' + icon + '" style="height: 11px;"></td><td><b>Hour</b></td><td ><b>Day</b></td><td ><b>Week</b></td><td></td></thead><tbody>' + '<tr><td><b>+</b></td><td >' + Utils.FormatNumToStr(income, false, 0) + '</td> <td >' + Utils.FormatNumToStr(income * 24, false, 0) + '</td> <td >' + Utils.FormatNumToStr(income * 24 * 7, false, 0) + '</td> <td ><i>«Production</i></td> </tr>' + '</tbody></table>';
  2135. }
  2136.  
  2137. function getGrowthTip() {
  2138. var populationData = city.populationData;
  2139. var img = populationData.growth > 1 ? (populationData.growth < 6 ? 'happy' : 'ecstatic') : populationData.growth < 0 ? (populationData.growth < -1 ? 'outraged' : 'sad') : 'neutral';
  2140. img = Utils.format('skin/smilies/{0}_x25.png', [img]);
  2141. // if (populationData.growth > 1) {
  2142. // img = populationData.growth < 6 ? 'happy' : 'ecstatic';
  2143. // } else if (populationData.growth < 1) {
  2144. // img = populationData.growth < 0 ? populationData.growth < -1 ? 'outraged' : 'sad' : 'neutral';
  2145. // }
  2146.  
  2147. var growthTip = '<table>\n <thead>\n <tr>\n <th><div class="icon" style="background-image:url(\'{0}\')"></div></td>\n <th colspan="2"><b>{1}</b></td>\n </tr>\n </thead>\n <tbody>{2}</tbody>\n <tfoot>\n <tr>\n <td class="icon incomeIcon"></td>\n <td></td>\n <td >{3}</td>\n </tr>\n <tr>\n <td class="icon populationImage"></td>\n <td></td>\n <td >{4}</td>\n </tr>\n <tr style="border-top:3px solid #FDF7DD">\n <td><b>Σ {5}</b></td>\n <td></td>\n <td >{6}</td>\n </tr>\n </tfoot>\n</table>';
  2148. var growthTr = '<tr class="data">\n <td class="icon {1}Icon"></td>\n <td></td>\n <td >{0}</td>\n</tr>';
  2149. var growthRows = '';
  2150. var incomeSum = 0
  2151. $.each(populationData.satisfaction, function(key, value) {
  2152. var total = 0;
  2153. if(key === 'total') return true;
  2154. if(typeof value === 'object') {
  2155. for(var type in value) {
  2156. total += value[type];
  2157. }
  2158. } else {
  2159. total += value
  2160. }
  2161. if(total) {
  2162. incomeSum += total;
  2163. growthRows += Utils.format(growthTr, [total, key])
  2164. }
  2165. });
  2166. return Utils.format(growthTip, [img, database.getGlobalData.getLocalisedString('Satisfaction') , growthRows, Utils.FormatNumToStr(incomeSum, false, 0), Utils.FormatNumToStr(populationData.currentPop, false, 0), (populationData.happiness >= 0 ? '+' : '-'), Utils.FormatNumToStr(populationData.happiness, false, 0)]);
  2167. }
  2168.  
  2169. function getPopulationTip() {
  2170. var populationData = city.populationData;
  2171. var populationTip = '<table>\n <thead>\n <td><img src="skin/resources/icon_population.png" style="height: 11px;" alt=""></td>\n <td><b>{0}</b></td>\n <td ><b>{1}</b></td>\n <td ><b>{2}</b></td>\n </thead>\n <tbody>\n <tr class="data">\n <td><b>Σ</b></td>\n <td >{3}</td>\n <td >{4}</td>\n <td >{5}</td>\n </tr>\n</table>';
  2172. return Utils.format(populationTip, [database.getGlobalData.getLocalisedString('Citizens'), database.getGlobalData.getLocalisedString('Population'), database.getGlobalData.getLocalisedString('Maximum'), Utils.FormatNumToStr(city._citizens, false, 0), Utils.FormatNumToStr(populationData.currentPop, false, 0), Utils.FormatNumToStr(populationData.maxPop, false, 0)]);
  2173. }
  2174.  
  2175. function getResearchTip(researchData) {
  2176. var premium = database.getGlobalData.hasPremiumFeature(Constant.Premium.RESEARCH_POINTS_BONUS)|| database.getGlobalData.hasPremiumFeature(Constant.Premium.RESEARCH_POINTS_BONUS_EXTREME_LENGTH);
  2177. researchData = researchData || city.research.researchData
  2178. var rows = '';
  2179. var tooltip = '<table>\n <thead>\n <tr>\n <th colspan="3"><div align="center">\n <img src="skin/layout/bulb-on.png" style="height: 15px; float: left">\n \n </div><b>{0}</b></th>\n </tr>\n </thead>\n <tbody>\n {1}\n </tbody>\n <tfoot>\n <tr style="border-top:3px solid #FDF7DD">\n <td><b>Σ</b></td>\n <td >{2}</td>\n <td >«Total</td>\n </tr>\n </tfoot>\n</table>';
  2180. var tr = '<tr class="data">\n <td >{2}</td>\n <td >{0}</td>\n <td >«{1}</td>\n</tr>';
  2181. var gameforgeResearch = researchData.researchBonus + researchData.premiumResearchBonus;
  2182. var gameforgeCultural = researchData.culturalGoods + researchData.premiumCulturalGoodsBonus;
  2183. var gameforgePremium = researchData.premiumScientistBonus;
  2184.  
  2185. rows = Utils.format(tr,[Utils.FormatNumToStr(researchData.scientists,false,0),
  2186. database.getGlobalData.getLocalisedString('Scientists'),
  2187. '+'
  2188. ]);
  2189. rows += Utils.format(tr,[Utils.FormatNumToStr(gameforgeResearch,false,2),
  2190. database.getGlobalData.getLocalisedString('research'),
  2191. '+'
  2192. ]);
  2193.  
  2194. if (premium){
  2195. rows += Utils.format(tr,[
  2196. Utils.FormatNumToStr(gameforgePremium,false, 2),
  2197. database.getGlobalData.getLocalisedString('premium'),
  2198. '+'])
  2199. }
  2200. rows += Utils.format(tr, [
  2201. Utils.FormatNumToStr(gameforgePremium+gameforgeResearch+researchData.scientists,false,2),
  2202. database.getGlobalData.getLocalisedString('Subtotal'),
  2203. '<b>Σ</b>'
  2204. ]).replace('class="data"','class="total"')
  2205. if(database.getGlobalData.getGovernmentType == Constant.Government.DEMOCRACY) {
  2206. rows += Utils.format(tr, [
  2207. Utils.FormatNumToStr(gameforgeCultural,false,2),
  2208. database.getGlobalData.getLocalisedString('Cultural Goods'),
  2209. '+'
  2210. ])
  2211. }
  2212. if(researchData.corruption) {
  2213. rows += Utils.format(tr, [
  2214. Utils.FormatNumToStr(researchData.corruption,false,2),
  2215. 'Corruption',
  2216. '-'
  2217. ])
  2218. }
  2219. return Utils.format(tooltip, [database.getGlobalData.getLocalisedString('Research'), rows, Utils.FormatNumToStr(researchData.total,false, 2)])
  2220. }
  2221.  
  2222. function getIncomingTip() {
  2223. var cRes = city.getResource(resourceName).getCurrent;
  2224. var rMov = database.getGlobalData.getResourceMovementsToCity(city.getId);
  2225. //if (rMov) rMov = rMov[0];
  2226. var table = '<table>\n <thead>{0}</thead>\n <tbody>{1}</tbody>\n <tfoot>{2}</tfoot>\n</table>';
  2227. var row = '<tr class="data">\n <td><div class="icon {0}Image"></div></td>\n <td>{1}</td>\n <td><i>«{2}</i></td>\n <td>{3}</td>\n</tr>\n<tr class="small data">\n <td colspan=3></td>\n <td>({4})</td>\n</tr>';
  2228. var header = '<tr>\n <th ><div class="icon merchantImage"></div></th>\n <th colspan="3">Transports</th>\n</tr>';
  2229. var subtotal = '<tr class="total">\n <td>=</td>\n <td>{0}</td>\n <td colspan=2><i>{1}</i></td>\n</tr>';
  2230. var footer = '<tr class="total">\n <td>Σ</td>\n <td colspan=3>{0}</td>\n</tr>';
  2231. if(rMov.length) {
  2232. var trades = '';
  2233. var transp = '';
  2234. var movTotal = 0;
  2235. for(var movID in rMov) {
  2236. if(rMov[movID].getResources[resourceName]) {
  2237. var origin = database.getCityFromId(rMov[movID].getOriginCityId);
  2238. var tMov = Utils.format(row, [
  2239. rMov[movID].getMission, Utils.FormatNumToStr(rMov[movID].getResources[resourceName], false, 0), origin ? origin.getName : rMov[movID].getOriginCityId, Utils.FormatRemainingTime(rMov[movID].getArrivalTime - $.now()), rMov[movID].isLoading ? 'Loading: ' + Utils.FormatRemainingTime(rMov[movID].getLoadingTime, false) : rMov[movID].getArrivalTime > $.now() ? 'en route' : 'Arrived'
  2240. ]);
  2241. if(rMov[movID].getMission == "trade")
  2242. trades += tMov; else if(rMov[movID].getMission == "transport")
  2243. transp += tMov;
  2244. movTotal += rMov[movID].getResources[resourceName]
  2245. }
  2246. }
  2247. if(trades === '' && transp === '') {
  2248. return ''
  2249. }
  2250. var body = trades + transp + Utils.format(subtotal, [
  2251. Utils.FormatNumToStr(movTotal, false, 0), ''
  2252. ]);
  2253. var foot = Utils.format(footer, [
  2254. Utils.FormatNumToStr((movTotal + cRes), false, 0)
  2255. ]);
  2256. var head = Utils.format(header, []);
  2257. return Utils.format(table, [head, body, foot]);
  2258. }
  2259. return ''
  2260. }
  2261.  
  2262. //TODO Redo this function
  2263. function getBuildingTooltip(building) {
  2264. if(!building || building.isMaxLevel) return '';
  2265. var uConst = (building.isUpgrading);
  2266. var resourceCost = building.getUpgradeCost;
  2267. var elem = '';
  2268. var time = 0;
  2269. for(var key in resourceCost) {
  2270. if(key == 'time') {
  2271. time = '<tr class="total"><td><img src="skin/resources/icon_time.png" style="height: 11px; float: left;"></td><td colspan=2 ><i>(' + Utils.FormatTimeLengthToStr(resourceCost[key], 3, ' ') + ')</i></td></tr>';
  2272. continue;
  2273. }
  2274. if(resourceCost[key]) {
  2275. elem += '<tr class="data"><td><div class="icon ' + key + 'Image"></div></td><td>' + Utils.FormatNumToStr(resourceCost[key], false, 0) + '</td>';
  2276. elem += (building.city().getResource(key).getCurrent < resourceCost[key] ? '<td class="red left">(' + Utils.FormatNumToStr(building.city().getResource(key).getCurrent - resourceCost[key], true, 0) + ')</td></tr>' : '<td><img src="skin/interface/check_mark_17px.png" style="height:11px; float:left;"></td></tr>')
  2277. }
  2278. }
  2279. elem = (elem !== '') ? '<table><thead><tr><th colspan=3 align="center"><b>' + (uConst ? 'Next Level' : 'Cost') + '</b></th></tr></thead><tbody>' + elem + '</tbody><tfoot>' + time + '</tfoot></table>' : '';
  2280. if(uConst) {
  2281. elem = '<table><thead><tr><th colspan=2><div class="prog" style="text-shadow:0 1px #FFFFFF"><b>Under Construction</b></div></th></tr></thead>' + '<tbody><tr class="data"><td></td><td>' + Utils.FormatFullTimeToDateString(building.getCompletionTime, true) + '</td></tr></tbody>' + '<tfoot><tr class="total"><td><img src="skin/resources/icon_time.png" style="height: 11px; float: left;"></td><td colspan=2 class="left"><i>(' + Utils.FormatTimeLengthToStr(building.getCompletionTime - $.now(), 3, ' ') + ')</i></td></tr></tfoot></table>' + elem
  2282. }
  2283. return elem
  2284. }
  2285.  
  2286. function getResourceTotalTip() {
  2287. var totals = {};
  2288. $.each(database.cities, function(cityId, city) {
  2289. $.each(Constant.Resources, function(key, resourceName) {
  2290. var res = city.getResource(resourceName);
  2291. if(!totals[resourceName]) {
  2292. totals[resourceName] = {}
  2293. }
  2294.  
  2295. totals[resourceName].total = totals[resourceName].total ? totals[resourceName].total + res.getCurrent : res.getCurrent;
  2296. totals[resourceName].income = totals[resourceName].income ? totals[resourceName].income + res.getProduction * 3600 - res.getConsumption : res.getProduction * 3600 - res.getConsumption;
  2297.  
  2298. })
  2299. });
  2300.  
  2301. var r = '';
  2302. var finalSums = {income: 0, total: 0, day: 0, week: 0};
  2303. $.each(totals, function(resourceName, data) {
  2304. var day = data.total + data.income * 24;
  2305. var week = data.total + data.income * 168;
  2306. r += Utils.format('<tr class="data">\n <td><div class="icon {0}Image"></div></td>\n <td >{1}</td>\n <td >{2}</td>\n <td >{3}</td>\n <td >{4}</td>\n</tr>', [resourceName, Utils.FormatNumToStr(data.income, false, 0), Utils.FormatNumToStr(data.total, false, 0) , Utils.FormatNumToStr(day, false, 0) , Utils.FormatNumToStr(week, false, 0)]);
  2307. finalSums.income += data.income;
  2308. finalSums.total += data.total;
  2309. finalSums.day += day;
  2310. finalSums.week += week
  2311. });
  2312. if(r === '') {
  2313. return ''
  2314. } else {
  2315. return Utils.format('<table>\n <thead>\n <td></td>\n <td><b>Income</b></td>\n <td ><b>Total</b></td>\n <td ><b>+24hrs</b></td>\n <td ><b>+7days</b></td>\n </thead>\n <tbody>\n {0}\n <tfoot>\n <td></td>\n <td >{1}</td>\n <td >{2}</td>\n <td >{3}</td>\n <td >{4}</td>\n </tfoot>\n </tbody>\n</table>', [r, Utils.FormatNumToStr(finalSums.income, false, 0) , Utils.FormatNumToStr(finalSums.total, false, 0) , Utils.FormatNumToStr(finalSums.day, false, 0) , Utils.FormatNumToStr(finalSums.week, false, 0)])
  2316. }
  2317. }
  2318.  
  2319. function getProgressTip() {
  2320. if (resourceName == 'population' || resourceName =='ui-corner-all'){return ''}; // temp fix for population progressbar
  2321. var storage = city.maxResourceCapacities;
  2322. var current = city.getResource(resourceName).getCurrent;
  2323. var fulltime = (city.getResource(resourceName).getFullTime || 0 - city.getResource(resourceName).getEmptyTime) * 3600000;
  2324. var progTip = '<table>\n <thead>\n <tr>\n <th></th>\n <th><b>Safe</b></th>\n <th ><b>Capacity</b></th>\n <th></th>\n </tr>\n </thead>\n <tbody>{0}\n <tr class="total">\n <td style="width:35px; background: url(\'{9}\');background-size: auto 45px;background-position: -3px -15px; \n background-repeat: no-repeat;"></td>\n <td>{1}</td>\n <td >{2}</td>\n <td ><i>«Maximum</i></td>\n </tr>\n <tr class="total">\n <td style="width:35px; background: url(\'{10}\');background-size: auto 45px;background-position: -3px -15px;\n background-repeat: no-repeat;"></tdstyle></td>\n <td>{3}</td>\n <td >{4}</td>\n <td ><i>«Used</i></td>\n </tr>\n <tr class="total">\n <td><b></b></td>\n <td>{5}</td>\n <td >{6}</td>\n <td ></td>\n </tr>\n </tbody>\n <tfoot>\n <tr class="small total" style="border-top:3px solid #FDF7DD">\n <td><b></b></td>\n <td></td>\n <td >{7}</td>\n <td >«To {8}</td>\n </tr>\n </tfoot>\n</table>';
  2325. var progTr = '<tr class="data">\n <td style="width:35px; background: url(\'{0}\');background-size: auto 40px;background-position: -3px -10px; \n background-repeat: no-repeat;">\n <td >{1}</td>\n <td >{2}</td>\n <td >«{3}</td>\n</tr>';
  2326. var rows = '';
  2327. $.each(storage.buildings, function(buildingName, data) {
  2328. rows += Utils.format(progTr, [Constant.BuildingData[buildingName].icon, Utils.FormatNumToStr(data.safe, false, 0), Utils.FormatNumToStr(data.storage, false, 0), database.getGlobalData.getLocalisedString(buildingName)])
  2329. });
  2330. return Utils.format(progTip,
  2331. [rows, Utils.FormatNumToStr(storage.safe, false, 0),
  2332. Utils.FormatNumToStr(storage.capacity, false, 0),
  2333. Utils.FormatNumToStr(Math.min(storage.safe, current), false, 0),
  2334. Utils.FormatNumToStr(Math.min(storage.capacity, current), false, 0),
  2335. Utils.FormatNumToStr(Math.min(1, current / storage.safe) * 100, false, 2) + '%',
  2336. Utils.FormatNumToStr(Math.min(1, current / storage.capacity) * 100, false, 2) + '%',
  2337. Utils.FormatTimeLengthToStr(fulltime),
  2338. fulltime < 0 ? 'empty' : 'full',
  2339. database.getGlobalData.hasPremiumFeature(Constant.Premium.STORAGECAPACITY_BONUS)?Constant.PremiumData[Constant.Premium.STORAGECAPACITY_BONUS].icon:'',
  2340. database.getGlobalData.hasPremiumFeature(Constant.Premium.SAFECAPACITY_BONUS)?Constant.PremiumData[Constant.Premium.SAFECAPACITY_BONUS].icon:''
  2341. ])
  2342. }
  2343.  
  2344. function getConsumptionTooltip(consumption, force) {
  2345. //future proofing stage 1 :D
  2346. if((consumption === 0 && !force) || resourceName !== Constant.Resources.WINE) {
  2347. return ''
  2348. } else return Utils.format('<table>\n <thead>\n <tr>\n <th><div class="icon {0}Image"></div></th>\n <th><b>{1}</b></th>\n <th ><b>{2}</b></th>\n <th ><b>{3}</b></th>\n </tr>\n </thead>\n <tbody>\n <tr class="data">\n <td><b>-</b></td>\n <td >{4}</td>\n <td >{5}</td>\n <td >{6}</td>\n </tr>\n </tbody>\n <tfoot>\n <tr class="small total">\n <td colspan="2"></td>\n <td>{7}</td>\n <td ><i>{8}</i></td>\n </tr>\n </tfoot>\n</table>', [
  2349. Constant.Resources.WINE, '1' + database.getGlobalData.getLocalisedString('hour'), '1' + database.getGlobalData.getLocalisedString('day'), '7' + database.getGlobalData.getLocalisedString('day'), Utils.FormatNumToStr(consumption, false, 0), Utils.FormatNumToStr(consumption * 24, false, 0), Utils.FormatNumToStr(consumption * 24 * 7, false, 0), ikariam.getNextWineTick(2), '«' + database.getGlobalData.getLocalisedString('Next Tick')
  2350. ])
  2351. }
  2352.  
  2353. function getProductionTip(income, force) {
  2354. if(income === 0 && !force) {
  2355. return ''
  2356. } else return Utils.format('<table>\n <thead>\n <th><div class="icon {0}Image"></div></th>\n <th>{1}</th>\n <th >{2}</th>\n <th >{3}</th>\n </thead>\n <tbody>\n <tr class="data">\n <td class="icon incomeIcon"></td>\n <td >{4}</td>\n <td >{5}</td>\n <td >{6}</td>\n </tr>\n </tbody>\n</table>', [
  2357. resourceName, '1' + database.getGlobalData.getLocalisedString('hour'), '1' + database.getGlobalData.getLocalisedString('day'), '7' + database.getGlobalData.getLocalisedString('day'), Utils.FormatNumToStr(income, false, 0), Utils.FormatNumToStr(income * 24, false, 0), Utils.FormatNumToStr(income * 24 * 7, false, 0), database.getGlobalData.getLocalisedString('Production')
  2358. ])
  2359. }
  2360.  
  2361. function getProductionConsumptionSubSumTip(income, consumption, force) {
  2362. if(income === 0 && consumption === 0 && !force) {
  2363. return ''
  2364. } else if (resourceName !== Constant.Resources.WINE) {
  2365. return getProductionTip(income, force)
  2366. } else if (income === 0) {
  2367. return getConsumptionTooltip(consumption, force)
  2368. } else return Utils.format('<table>\n <thead>\n <tr>\n <th><div class="icon {0}Image"></div></th>\n <th><b>{1}</b></th>\n <th ><b>{2}</b></th>\n <th ><b>{3}</b></th>\n </tr>\n </thead>\n <tbody>\n <tr class="data">\n <td class="icon incomeIcon"></td>\n <td >{4}</td>\n <td >{5}</td>\n <td >{6}</td>\n </tr>\n <tr class="data">\n <td><b>-</b></td>\n <td >{7}</td>\n <td >{8}</td>\n <td >{9}</td>\n </tr>\n <tr class="total">\n <td>{10}</td>\n <td >{11}</td>\n <td >{12}</td>\n <td >{13}</td>\n </tr>\n </tbody>\n <tfoot>\n <tr class="small total">\n <td colspan="2"></td>\n <td>{14}</td>\n <td ><i>{15}</i></td>\n </tr>\n </tfoot>\n</table>', [
  2369. resourceName,
  2370. '1' + database.getGlobalData.getLocalisedString('hour'),
  2371. '1' + database.getGlobalData.getLocalisedString('day'),
  2372. '7' + database.getGlobalData.getLocalisedString('day'),
  2373.  
  2374. Utils.FormatNumToStr(income, false, 0),
  2375. Utils.FormatNumToStr(income * 24, false, 0),
  2376. Utils.FormatNumToStr(income * 24 * 7, false, 0),
  2377.  
  2378. Utils.FormatNumToStr(consumption, false, 0),
  2379. Utils.FormatNumToStr(consumption * 24, false, 0),
  2380. Utils.FormatNumToStr(consumption * 24 * 7, false, 0),
  2381. (income > consumption?'+':'-'),
  2382. Utils.FormatNumToStr((income - consumption), false, 0),
  2383. Utils.FormatNumToStr((income - consumption) * 24, false, 0),
  2384. Utils.FormatNumToStr((income - consumption) * 24 * 7, false, 0),
  2385.  
  2386. ikariam.getNextWineTick(2), '«' + database.getGlobalData.getLocalisedString('Next Tick')
  2387. ])
  2388. }
  2389.  
  2390. function getImage(unitID) { //Todo pull into css
  2391. // /skin/characters/fleet/60x60/ship_submarine_faceright.png
  2392. // /skin/characters/military/x60_y60/y60_medic_faceright.png
  2393. return (Constant.UnitData[unitID].type == 'fleet') ? 'skin/characters/fleet/60x60/' + unitID + '_faceright.png' : 'skin/characters/military/x60_y60/y60_' + unitID + '_faceright.png'
  2394. }
  2395. }
  2396. },
  2397. cssResLoaded : function() {
  2398. var ret = this._cssResLoaded;
  2399. this._cssResLoaded = true;
  2400. return ret;
  2401. },
  2402. Init : function() {
  2403.  
  2404. this.SidePanelButton();
  2405. events(Constant.Events.DATABASE_LOADED).sub(function(){
  2406. this.LoadCSS();
  2407. this.DrawContentBox();
  2408. }.bind(render));
  2409.  
  2410. events(Constant.Events.MODEL_AVAILABLE).sub(function(){
  2411. this.DrawTables();
  2412. this.setCommonData();
  2413. this.RestoreDisplayOptions();
  2414. this.startMonitoringChanges();
  2415. this.cityChange(ikariam.CurrentCityId);
  2416. }.bind(render));
  2417.  
  2418. },
  2419. startMonitoringChanges : function() {
  2420. events(Constant.Events.TAB_CHANGED).sub(function (tab) {
  2421. this.stopResourceCounters();
  2422. switch (tab) {
  2423. case 0:
  2424. this.startResourceCounters();
  2425. break;
  2426. case 1:
  2427. this.updateCitiesBuildingData();
  2428. break;
  2429. case 2:
  2430. this.updateCitiesArmyData();
  2431. break;
  2432. case 3:
  2433. this.redrawSettings();
  2434. break;
  2435. }
  2436. }.bind(render));
  2437. events(Constant.Events.TAB_CHANGED).pub(database.settings.window.activeTab); //TODO Find a decent place for this
  2438. //cityChange(newCityID)
  2439. events('cityChanged').sub(this.cityChange.bind(render));
  2440.  
  2441. // updateChangesForCityBuilding(city,changes)
  2442. // change:{position:pos, name:oldBuildingName}
  2443. events(Constant.Events.BUILDINGS_UPDATED).sub(this.updateChangesForCityBuilding.bind(render));
  2444.  
  2445. // globalDataUpdated(changes)
  2446. // change:{type:'research/government/finance', subType:'topic'
  2447. events(Constant.Events.GLOBAL_UPDATED).sub(this.updateGlobalData.bind(render));
  2448.  
  2449. // movementsUpdated(changedCitiesIDs)
  2450. events(Constant.Events.MOVEMENTS_UPDATED).sub(this.updateMovementsForCity.bind(render));
  2451.  
  2452. // resourcesUpdated(city,changes) -> irrelevant if dynamic update
  2453. events(Constant.Events.RESOURCES_UPDATED).sub(this.updateResourcesForCity.bind(render));
  2454.  
  2455. //cityUpdated(id, changes)
  2456. // changes:[dataName]
  2457. events(Constant.Events.CITY_UPDATED).sub(this.updateCityDataForCity.bind(render));
  2458.  
  2459. events(Constant.Events.MILITARY_UPDATED).sub(this.updateChangesForCityMilitary.bind(render));
  2460. events(Constant.Events.PREMIUM_UPDATED).sub(this.updateGlobalData.bind(render));
  2461. },
  2462. cityChange : function(cid) {
  2463. var city = database.getCityFromId(cid);
  2464. $('#SITRBoard tr.current,#SITRBoard tr.selected').removeClass('selected current');
  2465. if(city) {
  2466. this.getAllRowsForCity(city).addClass('selected').addClass((isChrome) ? 'current' : 'selected')
  2467. }
  2468. },
  2469. getHelpTable : function(){
  2470. var elems = '<div id="HelpTab"><div>';
  2471. //Todo, rip this into constants and build dynamicly
  2472. var inits = '<div class="options" style="clear:left "><span class="category">Initialize Board</span>'
  2473. + ' 1. <span id="setingsTownhall" class="clickable"><b>> Click <</b></span> on your Town Hall and go through each town with that view open <br>'
  2474. + ' 2. <span id="settingsMilitary" class="clickable"><b>> Click <</b></span> on the Troops in town tab on left side and go through each town with that view open<br>'
  2475. + ' 3. <span id="settingsMuseum" class="clickable"><b>> Click <</b></span> on Museum and then the "Distribute Cultural Treaties" tab<br>'
  2476. + ' 4. <span id="settingsResearch" class="clickable"><b>> Click <</b></span> on Research Advisor and then click on each of the 4 research tabs in the left window<br>'
  2477. + ' 5. <span id="settingsPalace" class="clickable"><b>> Click <</b></span> on your Palace<br>'
  2478. + ' 6. <span id="settingsFinance" class="clickable"><b>> Click <</b></span> on your Finance tab<br>'
  2479. + ' 7. <span id="settingsShop" class="clickable"><b>> Click <</b></span> on the "Ambrosia shop"<br>'
  2480. + '</div>';
  2481. var features = '<div class="options">'
  2482. + '<span class="category">Re-Order Towns</span>On any tab, drag the resource icon to the left of the town name'
  2483. + '<span class="category">Reset Position</span>Right click on the SITR menu button on the left side page menu'
  2484. + '<span class="category">Hotkeys</span>'
  2485. + '1, 2, 3 ... 0, -, = : Navigate to town 1 to 12<br>'
  2486. + 'SHIFT + 1/2/3 : Navigate to City/Building/Army tab<br>'
  2487. + 'Q, W, E : Navigate to World/Island/City view<br>'
  2488. + 'SHIFT + Q, W, E, R : Navigate to City/Military/Research/Diplomacy advisor<br>'
  2489. + 'Spacebar: Minimise/Maximise the board<br>'
  2490. + '</div>';
  2491. features += '<div class="options">'
  2492. + '<span class="category"></span>'
  2493. + ''
  2494. + ''
  2495. + ''
  2496. + '</div>';
  2497. // add instructions
  2498. elems += features+inits +'<div style="clear:left"></div>';
  2499. elems += '</div></div>'
  2500. return elems
  2501. },
  2502. getSettingsTable :function(){
  2503. //TODO this needs to itterate through options and build a list with localisation
  2504.  
  2505. //format 1->3 name, localname, localdescription, value
  2506. var checkbox = '<span data-tooltip="{2}"><input type="checkbox" id="SITR_{0}" {3} /><label for="SITR_{0}">{1}</label></span>';
  2507.  
  2508. // format name, localname, options
  2509. var combo = '<label for="SITR_{0}">{1}</label><select id="SITR_{0}")>{2}</select>';
  2510.  
  2511. // format value, text, selected
  2512. var comboOption = '<option value="{0}" {2}>{1}</option>'
  2513.  
  2514. // format name, options
  2515. var category = '<span class="category">{0}</span>{1}';
  2516.  
  2517. var elems ='';
  2518.  
  2519. var settings = {};
  2520.  
  2521. $.each(Constant.SettingCategories, function(key, name){
  2522. settings[name] = [];
  2523. });
  2524.  
  2525. // build each option html and place in the array of the category
  2526. $.each(Constant.Settings, function(key, name){
  2527. if (database.settings[name] && database.settings[name].category != 'ignore'){
  2528. switch(database.settings[name].type){
  2529. case 'boolean': settings[database.settings[name].category].push(Utils.format(checkbox, [name,database.settings[name].name, database.settings[name].description, database.settings[name].value?'checked="checked"':'']));
  2530. break;
  2531. case 'array': break;
  2532. break;
  2533. case 'number':
  2534. // not sure why, but i wrote it like this
  2535. if (database.settings[name].choices){
  2536. settings[database.settings[name].category].push(Utils.format(combo,[name,
  2537. database.settings[name].name,
  2538. (function(val, choices){
  2539. var elems = '';
  2540. $.each(choices, function(i, value){
  2541. elems += Utils.format(comboOption,[value,value+'h',(val==value?'selected=selected':'')])
  2542. });
  2543. return elems
  2544. })(database.settings[name].value,Constant.SettingData[name].choices)]));
  2545. }
  2546. else {
  2547. //Texttual input
  2548. }
  2549. break;
  2550. }
  2551. }
  2552. });
  2553.  
  2554. // itterate the categories and push options into option divs (max 7 lines per div)
  2555. var i = 0;var j = 0;
  2556. $.each(settings, function(catName, html){
  2557. j += html.length + 1;
  2558. if (j>=7 || i== 0){
  2559. if (i !== 0){
  2560. elems+='</div>'
  2561. }
  2562. elems +='<div class="options">'
  2563. j = 0;
  2564. }
  2565. elems += Utils.format(category, [database.getGlobalData.getLocalisedString(catName),html.join('')]);
  2566. i++;
  2567. });
  2568. elems+='</div>'
  2569.  
  2570. // add version
  2571. elems += '<div style="clear:left"><p>&nbsp;Current version: ' + SITR.version + '</p></div>'
  2572.  
  2573. // add buttons
  2574. elems += '<div class="buttons">' + '<button data-tooltip="Reset all settings to default" id="SITR_Reset_Button">Reset</button>' + '<button data-tooltip="Goto the scripts Userscripts.com website " id="SITR_Website_Button">Website</button>' + '<button data-tooltip="Force a check for updates" id="SITR_Update_Button">Check for updates</button>' + '<button data-tooltip="Report a bug in the script" id="SITR_Bug_Button">Report Bug</button>'
  2575.  
  2576. //wrap
  2577. elems = '<div>' + elems + '</div>'
  2578.  
  2579. return elems
  2580. },
  2581. DrawHelp : function(){
  2582. $('#HelpTab').html(this.getHelpTable())
  2583. },
  2584. DrawSettings : function() {
  2585. $('#SettingsTab').html(this.getSettingsTable())
  2586. .on("click", "#setingsTownhall",function() {
  2587. ikariam.loadUrl(ikariam.viewIsCity, "city", ikariam.getCurrentCity.getBuildingFromName(Constant.Buildings.TOWN_HALL).getUrlParams)
  2588. })
  2589. .on("click", "#settingsMilitary",function() {
  2590. ikariam.loadUrl(ikariam.viewIsCity, "city", {view:'cityMilitary', activeTab:'tabUnits'} )
  2591. })
  2592. .on("click", "#settingsMuseum",function() {
  2593. ikariam.loadUrl(ikariam.viewIsCity, "city", {view:'culturalPossessions_assign',activeTab:'tab_culturalPossessions_assign'})
  2594. })
  2595. .on("click", "#settingsResearch",function() {
  2596. ikariam.loadUrl(ikariam.viewIsCity, "city", {view:'researchAdvisor'})
  2597. })
  2598. .on("click", "#settingsPalace",function() {
  2599. var capital = ikariam.getCapital;
  2600. if (capital){
  2601. ikariam.loadUrl(ikariam.viewIsCity, "city", capital.getBuildingFromName(Constant.Buildings.PALACE).getUrlParams)
  2602. }
  2603. else alert('Please visit your capital city first')
  2604. })
  2605. .on("click", "#settingsFinance",function() {
  2606. ikariam.loadUrl(ikariam.viewIsCity, "city", {view:'finances'} )
  2607. })
  2608. .on("click", "#settingsShop",function() {
  2609. ikariam.loadUrl(ikariam.viewIsCity, "city", {view:'premium'} )
  2610. })
  2611. //Event Handlers
  2612. .on("change", "#SITR_onTop", function() {
  2613. database.settings.onTop.value = this.checked;
  2614. render.mainContentBox.css('z-index', this.checked ? 65112 : 61);
  2615. })
  2616. .on("change", "#SITR_windowTennis", function() {
  2617. database.settings.windowTennis.value = this.checked;
  2618. if (!this.checked){
  2619. render.mainContentBox.css('z-index', database.settings.onTop.value ? 65112 : 61);
  2620. }
  2621. else {
  2622. render.mainContentBox.trigger('mouseenter')
  2623. }
  2624. })
  2625. .on("change", "#SITR_fullArmyTable", function() {
  2626. database.settings.fullArmyTable.value = this.checked;
  2627. render.updateCitiesArmyData()
  2628. })
  2629. .on("change", "#SITR_hideOnWorldView", function() {
  2630. database.settings.hideOnWorldView.value = this.checked;
  2631. })
  2632. .on("change", "#SITR_hideOnIslandView", function() {
  2633. database.settings.hideOnIslandView.value = this.checked;
  2634. })
  2635. .on("change", "#SITR_enableAutoUpdates", function() {
  2636. database.settings.autoUpdates.value = this.checked;
  2637. })
  2638. .on("change", "#SITR_smallFont", function() {
  2639. database.settings.smallFont.value = this.checked;
  2640. if(this.checked) {GM_addStyle("#SITRBoard {font-size:8pt}")}else {GM_addStyle("#SITRBoard {font-size:inherit}")}
  2641. })
  2642. .on("change", "#SITR_compressedBuildingList", function() {
  2643. database.settings.compressedBuildingList.value = this.checked;
  2644. render.cityRows.building = {};
  2645. $('table.buildings').html(render.getBuildingTable());
  2646. render.updateCitiesBuildingData();
  2647. $.each(database.cities, function(cityId, city) {
  2648. render.setCityName(city);
  2649. render.setActionPoints(city);
  2650. $.each(database.settings[Constant.Settings.CITY_ORDER].value, function (idx, val) {
  2651. $('#' + 'building' + '_' + val).appendTo($('#' + 'building' + '_' + val).parent())
  2652. })
  2653. })
  2654. })
  2655. .on('change',"#SITR_wineWarningTime", function() {
  2656. database.settings.wineWarningTime.value = this.value;
  2657. })
  2658. .on("click", "#SITR_Website_Button", function() {
  2659. GM_openInTab('http://userscripts.org/scripts/show/' + SITR.scriptId);
  2660. })
  2661. .on("click", "#SITR_Reset_Button",function() {
  2662. SITR.HardReset();
  2663. })
  2664. .on("click","#SITR_Update_Button", function() {
  2665. SITR.CheckForUpdates.call(SITR, true);
  2666. })
  2667. .on("click","#SITR_Bug_Button", function() {
  2668. GM_openInTab('http://userscripts.org/topics/118866');
  2669. })
  2670. .on("change", "input[type='checkbox']", function(){
  2671. this.blur()
  2672. });
  2673. //Additional Stuff
  2674. $("#SITR_Reset_Button").button({icons: {primary: "ui-icon-alert"}, text: true});
  2675. $("#SITR_Website_Button").button({icons: {primary: "ui-icon-home"}, text: true});
  2676. $("#SITR_Update_Button").button({icons: {primary: "ui-icon-info"}, text: true});
  2677. $("#SITR_Bug_Button").button({icons: {primary: "ui-icon-notice"}, text: true});
  2678. },
  2679. toast : function(sMessage) {
  2680. $('<div>').addClass("ui-tooltip-content ui-widget-content").text(sMessage).appendTo($(document.createElement("div")).addClass("ui-helper-reset ui-tooltip ui-tooltip-pos-bc ui-widget").css({position: 'relative', display: 'inline-block', left: 'auto', top: 'auto'}).show().appendTo($(document.createElement("div")).addClass("toast").appendTo(document.body).delay(100).fadeIn("slow", function() {
  2681. $(this).delay(2000).fadeOut("slow", function() {
  2682. $(this).remove();
  2683. });
  2684. })));
  2685. },
  2686. RestoreDisplayOptions : function() {
  2687. render.mainContentBox.css('left', database.settings.window.left);
  2688. render.mainContentBox.css('top', database.settings.window.top);
  2689. this.$tabs.tabs('select', database.settings.window.activeTab);
  2690. if(!(ikariam.viewIsWorld && database.settings.hideOnWorldView.value || ikariam.viewIsIsland && database.settings.hideOnIslandView.value) && database.settings.window['visible'])
  2691. this.mainContentBox.fadeToggle('slow');
  2692. },
  2693. SaveDisplayOptions : function() {
  2694. if(database.settings)
  2695. try {
  2696. database.settings.addOptions({window: {
  2697. left : render.mainContentBox.css('left'),
  2698. top : render.mainContentBox.css('top'),
  2699. visible : (ikariam.viewIsWorld && database.settings.hideOnWorldView.value || ikariam.viewIsIsland && database.settings.hideOnIslandView.value) ? database.settings.window.visible : (render.mainContentBox.css('display') != 'none'),
  2700. activeTab: render.$tabs.tabs('option', 'active')}
  2701. })
  2702. } catch(e) {
  2703. SITR.error('SaveDisplayOptions', e)
  2704. }
  2705. },
  2706. SidePanelButton : function() {
  2707. $('#js_viewCityMenu').find('li.SITR_Menu')
  2708. .on("click", function(event) {render.ToggleMainBox();})
  2709. .on("contextmenu", function(event) {
  2710. event.preventDefault();
  2711. database.settings.window.left = 150;
  2712. database.settings.window.top = 180;
  2713. render.mainContentBox.css('left', database.settings.window.left);
  2714. render.mainContentBox.css('top', database.settings.window.top);
  2715. });
  2716. $(document).on('keydown', function(event) {
  2717. var index = -1;
  2718. var type = event.target.nodeName.toLowerCase();
  2719. if(type === 'input' || type === 'textarea' || type === 'select')
  2720. return true;
  2721.  
  2722. if(event.which === 32) {
  2723. event.stopImmediatePropagation();
  2724. render.ToggleMainBox();
  2725. return false
  2726. }
  2727. if(event.originalEvent.shiftKey) {
  2728.  
  2729. index = [49, 50, 51].indexOf(event.which);
  2730. if(index !== -1) {
  2731. render.$tabs.tabs('option', 'active', index);
  2732. return false
  2733. } else {
  2734. switch(event.which){
  2735. case 81:
  2736. $('#js_worldMapLink').find('a').click();
  2737. break;
  2738. case 87:
  2739. $('#js_islandLink').find('a').click();
  2740. break;
  2741. case 69:
  2742. $('#js_cityLink').find('a').click();
  2743. break;
  2744. }
  2745. }
  2746. } else {
  2747. var keycodes = [49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 173, 61];
  2748. index = keycodes.indexOf(event.which);
  2749. if(index !== -1) {
  2750. if(index < database.settings.cityOrder.value.length) {
  2751. //Todo: create a page changing class
  2752. $('#resource_' + database.settings.cityOrder.value[index] +' .city_name .clickable').trigger('click');
  2753. return false
  2754. }
  2755. } else {
  2756. switch(event.which){
  2757. case 81:
  2758. $('#js_GlobalMenu_cities').click();
  2759. break;
  2760. case 87:
  2761. $('#js_GlobalMenu_military').click();
  2762. break;
  2763. case 69:
  2764. $('#js_GlobalMenu_research').click();
  2765. break;
  2766. case 82:
  2767. $('#js_GlobalMenu_diplomacy').click();
  2768. break;
  2769. }
  2770. }
  2771. }
  2772. })
  2773.  
  2774. },
  2775. ToggleMainBox : function() {
  2776. database.settings.window.visible = (this.mainContentBox.css('display') == 'none');
  2777. this.mainContentBox.fadeToggle("slow");
  2778. },
  2779. DrawTables : function() {
  2780. if($(this.mainContentBox)) {
  2781. $('#ArmyTab').html(this.getArmyTable());
  2782. $('#ResTab').html(this.getResourceTable());
  2783. $('#BuildTab').html(this.getBuildingTable());
  2784. this.DrawSettings();
  2785. this.DrawHelp();
  2786. this.toolTip.init();
  2787.  
  2788. $('#ResTab, #BuildTab, #ArmyTab').each(function () {
  2789. $(this).sortable({
  2790. // Add widths to td's to prevent cell collapse, add borders to td's to maintain approx positioning
  2791. helper:function (e, ui) {
  2792. ui.children('td').each(function () {
  2793. $(this).width(Math.round($(this).width()));
  2794. $(this).hasClass('building') && $(this).css('border', '1px solid transparent');
  2795.  
  2796. });
  2797. ui.parents('div[role=tabpanel]').each(function () {
  2798. $(this).width(Math.round($(this).width()));
  2799. });
  2800. return ui;
  2801. },
  2802. handle:'.city_name .icon',
  2803. cursor:"move",
  2804. axis:'y',
  2805. items:'tbody tr',
  2806. container:'tbody',
  2807. revert:200,
  2808. //remove widths from td's
  2809. stop:function (event, ui) {
  2810. ui.item.parents("div[role=tabpanel]").css("width", "");
  2811. ui.item.children("td").css("width", "").css("border", "");
  2812. database.settings[Constant.Settings.CITY_ORDER].value = ui.item.parents('.ui-sortable').sortable('toArray').map(function (item) {
  2813. return parseInt(item.split('_').pop())
  2814. });
  2815. //Re=order the other tables
  2816. $.each(
  2817. [
  2818. 'building' ,
  2819. 'resource',
  2820. 'army'
  2821. ], function (idx, type) {
  2822. if ($(this).parents('.ui-sortable').attr('id') !== type) {
  2823. $.each(database.settings[Constant.Settings.CITY_ORDER].value, function (idx, val) {
  2824. $('#' + type + '_' + val).appendTo($('#' + type + '_' + val).parent())
  2825. })
  2826. }
  2827. });
  2828. }
  2829. })
  2830. });
  2831. //initialise the row orders
  2832. $.each(
  2833. [
  2834. 'building' ,
  2835. 'resource',
  2836. 'army'
  2837. ], function (idx, type) {
  2838. $.each(database.settings[Constant.Settings.CITY_ORDER].value, function (idx, val) {
  2839. $('#' + type + '_' + val).appendTo($('#' + type + '_' + val).parent())
  2840. })
  2841. });
  2842. }
  2843. this.AttachClickHandlers();
  2844. },
  2845. getResourceTable : function() {
  2846. var header = ' <colgroup span="3"/>\n <colgroup span="3"/>\n <colgroup span="2"/>\n <colgroup span="2"/>\n <colgroup span="2"/>\n <colgroup span="2"/>\n <colgroup span="2"/>\n <colgroup span="2"/>\n<thead>\n<tr class="header_row">\n <th class="city_name">{0}</th>\n <th class="action_points icon actionpointImage" data-tooltip="{1}"></th>\n <th class="actions"></th>\n <th class="citizen_header icon populationImage" data-tooltip="{2}" style="cursor:pointer;" onclick="ajaxHandlerCall(\'?view=ikipedia&helpId=3\');return false;"></th>\n <th class="satisfaction_header icon happyImage" style="cursor:pointer;" onclick="ajaxHandlerCall(\'?view=ikipedia&helpId=3\');return false;"></th>\n <th class="growth_header icon growthImage"></th>\n <th class="research_header icon researchImage" data-tooltip="{3}" style="cursor:pointer;" onclick="ajaxHandlerCall(\'?view=ikipedia&helpId=0&subHelpId=2\');return false;"></th>\n <th class="gold_header icon goldImage" data-tooltip="{4}" style="cursor:pointer;" onclick="ajaxHandlerCall(\'?view=ikipedia&helpId=4\');return false;"></th>\n <th class="wood_header icon woodImage" colspan="2" data-tooltip="{5}" style="cursor:pointer;" onclick="ajaxHandlerCall(\'?view=ikipedia&helpId=5\');return false;"></th>\n <th class="wine_header icon wineImage" colspan="2" data-tooltip="{6}" style="cursor:pointer;" onclick="ajaxHandlerCall(\'?view=ikipedia&helpId=6\');return false;"></th>\n <th class="marble_header icon marbleImage" colspan="2" data-tooltip="{7}" style="cursor:pointer;" onclick="ajaxHandlerCall(\'?view=ikipedia&helpId=6\');return false;"></th>\n <th class="glass_header icon glassImage" colspan="2" data-tooltip="{8}" style="cursor:pointer;" onclick="ajaxHandlerCall(\'?view=ikipedia&helpId=6\');return false;"></th>\n <th class="sulfur_header icon sulfurImage" colspan="2" data-tooltip="{9}" style="cursor:pointer;" onclick="ajaxHandlerCall(\'?view=ikipedia&helpId=6\');return false;"></th>\n</tr>\n</thead>';
  2847. var table = '<table class="resources">\n {0}\n <tbody>{1}</tbody>\n <tfoot>{2}</tfoot>\n</table>';
  2848. var resourceRow = '<tr id="resource_{0}">\n <td class="city_name">\n <span></span>\n <span class="clickable"></span>\n <sub></sub>\n </td>\n <td class="action_points"></td>\n <td class="sitractions">\n <div class="transport"></div>\n <div class="deploymentfleet"></div>\n <div class="deploymentarmy"></div>\n </td>\n <td class="population" data-tooltip="dynamic">\n <span></span>\n <span></span>\n <div class="progressbar ui-progressbar ui-widget ui-widget-content ui-corner-all" data-tooltip="dynamic">\n <div class="ui-progressbar-value ui-widget-header ui-corner-left" style="width: 95%"></div>\n </div>\n </td>\n <td class="population_growth" data-tooltip="dynamic">\n <img align=right height=18 hspace=2 vspace=0></td>\n <td class="population_happiness"></td>\n <td class="research" data-tooltip="dynamic"></td>\n <td class="gold_income">\n <span></span>\n <span class="Red"></span>\n </td>\n {1}\n</tr>\n';
  2849. var resourceCell = '<td class="resource {0}">\n <span class="icon safeImage"></span>\n <span class="current"></span>\n <span class="incoming" data-tooltip="dynamic"></span>\n <div class="progressbar ui-progressbar ui-widget ui-widget-content ui-corner-all" data-tooltip="dynamic">\n <div class="ui-progressbar-value ui-widget-header ui-corner-left" style="width: 95%"></div>\n </div>\n</td>\n<td class="resource {0}">\n <span class="prodconssubsum production Green" data-tooltip="dynamic"></span>\n <span class="prodconssubsum consumption Red" data-tooltip="dynamic"></span>\n <span class="emptytime Red"></span>\n</td>';
  2850. var footer = '<tr>\n <td ></td>\n <td id="t_sigma" class="total" colspan="2" data-tooltip="dynamic">Σ</td>\n <td id="t_population" class="total" colspan=3></td>\n <td id="t_research" class="total" data-tooltip="dynamic"></td>\n <td id="t_goldincome" class="total" data-tooltip="dynamic">\n <span class="Green"></span>\n <span class="Red"></span>\n </td>\n <td id="t_currentwood" class="total"></td>\n <td id="t_woodincome" class="total" data-tooltip="dynamic">\n <span class="Green"></span>\n <span class="Red"></span>\n </td>\n <td id="t_currentwine" class="total"></td>\n <td id="t_wineincome" class="total" data-tooltip="dynamic">\n <span class="Green"></span>\n <span class="Red"></span>\n </td>\n <td id="t_currentmarble" class="total"></td>\n <td id="t_marbleincome" class="total"data-tooltip="dynamic">\n <span class="Green"></span>\n <span class="Red"></span>\n </td>\n <td id="t_currentglass" class="total"></td>\n <td id="t_glassincome" class="total" data-tooltip="dynamic">\n <span class="Green"></span>\n <span class="Red"></span>\n </td>\n <td id="t_currentsulfur" class="total"></td>\n <td id="t_sulfurincome" class="total" data-tooltip="dynamic">\n <span class="Green"></span>\n <span class="Red"></span>\n </td>\n</tr>';
  2851.  
  2852. return Utils.format(table, [getHead(), getBody(), getFooter()]);
  2853.  
  2854. function getHead() {
  2855. return Utils.format(header, [
  2856. database.getGlobalData.getLocalisedString("cities"), database.getGlobalData.getLocalisedString("ActionPoints"), database.getGlobalData.getLocalisedString('citizens'), database.getGlobalData.getLocalisedString('researchpoints'), database.getGlobalData.getLocalisedString("gold"), database.getGlobalData.getLocalisedString("wood"), database.getGlobalData.getLocalisedString("wine"), database.getGlobalData.getLocalisedString("marble"), database.getGlobalData.getLocalisedString("crystal"), database.getGlobalData.getLocalisedString("sulfur")])
  2857. }
  2858.  
  2859. function getBody() {
  2860. var rows = '';
  2861. $.each(database.cities, function(cityId, city) {
  2862. var resourceCells = '';
  2863. $.each(Constant.Resources, function(key, resourceName) {
  2864. resourceCells += Utils.format(resourceCell, [resourceName])
  2865. });
  2866. rows += Utils.format(resourceRow, [city.getId, resourceCells])
  2867. });
  2868. return rows;
  2869. }
  2870.  
  2871. function getFooter() {
  2872. return footer;
  2873. }
  2874. },
  2875. getArmyTable : function() {
  2876. var table = '<table class="army">\n {0}\n <tbody>{1}</tbody>\n <tfoot>{2}</tfoot>\n</table>';
  2877. var headerRow = '<thead><tr class="header_row">\n <th class="city_name">{0}</th>\n <th data-tooltip="{1}" class="icon actionpointImage action_points"></th>\n <th></th>\n {2}\n</tr></thead>';
  2878. var headerCell = '<th data-tooltip="{0}" style="background:url(\'{1}\') no-repeat center center;background-size: 26px auto;cursor: pointer;" colspan="2" class="army unit icon {2}" onclick="ajaxHandlerCall(\'?view=unitdescription&helpId=9&unitId={3}\'); return false;">&nbsp;</th>\n\n';
  2879. var bodyRow = '<tr id="army_{0}">\n <td class="city_name"><img><span class="clickable"></span><sub></sub></td>\n <td class="action_points">\n <td class="sitractions">\n <div class="transport"></div>\n <div class="deploymentfleet"></div>\n <div class="deploymentarmy"></div>\n </td>\n {1}\n</tr>';
  2880. var bodyCell = '<td style="" class="army unit {0}">\n <span>{1}</span>\n</td>\n<td style="" class="army movement {0}" data-tooltip="dynamic">\n <span class="More Green {0}">{2}</span>\n <span class="More Blue {0}">{3}</span>\n</td>';
  2881. var footerRow = '<tr class="totals_row">\n <td class="city_name"></td>\n <td></td>\n <td class="sigma">Σ</td>\n {0}\n</tr>';
  2882. var footerCell = '<td class="army total {0} unit">\n <span></span>\n</td>\n<td style="" class="army total {0} movement">\n <span class="More Green"></span>\n <span class="More Blue"></span>\n</td>';
  2883.  
  2884. return Utils.format(table, [getHead(), getBody(), getFooter()]);
  2885.  
  2886. function getHead() {
  2887. var headerCells = '';
  2888. var cols = '<colgroup span=3>';
  2889. for(var category in Constant.unitOrder) {
  2890. cols += '<colgroup>';
  2891. $.each(Constant.unitOrder[category], function(index, value) {
  2892. headerCells += Utils.format(headerCell, [database.getGlobalData.getLocalisedString(value), getImage(value), value, Constant.UnitData[value].id]);
  2893. cols += '<col><col>'
  2894. });
  2895. cols += '</colgroup>'
  2896. }
  2897. return cols + Utils.format(headerRow, [database.getGlobalData.getLocalisedString("cities"), database.getGlobalData.getLocalisedString("ActionPoints"), headerCells])
  2898. }
  2899.  
  2900. function getBody() {
  2901. var body = '';
  2902. $.each(database.cities, function(cityId, city) {
  2903. var rowCells = '';
  2904. for(var category in Constant.unitOrder) {
  2905. $.each(Constant.unitOrder[category], function(index, value) {
  2906. var builds = city.getUnitBuildsByUnit(value);
  2907. rowCells += Utils.format(bodyCell, [value, city.military.getUnits.getUnit(value) || '', builds[value] ? builds[value] : '', '' ])
  2908.  
  2909. })
  2910. }
  2911. body += Utils.format(bodyRow, [city.getId, rowCells])
  2912. });
  2913. return body
  2914. }
  2915.  
  2916. function getFooter() {
  2917. var footerCells = '';
  2918. for(var category in Constant.unitOrder) {
  2919. $.each(Constant.unitOrder[category], function(index, value) {
  2920. footerCells += Utils.format(footerCell, [value])
  2921. })
  2922. }
  2923. return Utils.format(footerRow, [footerCells])
  2924. }
  2925.  
  2926. function getImage(unitID) { //Todo pull into css
  2927. // /skin/characters/fleet/60x60/ship_submarine_faceright.png
  2928. // /skin/characters/military/x60_y60/y60_medic_faceright.png
  2929. return (Constant.UnitData[unitID].type == 'fleet') ? 'skin/characters/fleet/60x60/' + unitID + '_faceright.png' : 'skin/characters/military/x60_y60/y60_' + unitID + '_faceright.png'
  2930. }
  2931.  
  2932. },
  2933. getBuildingTable : function() {
  2934. var table = '<table class="buildings">\n{0}\n <tbody>{1}</tbody>\n</table>';
  2935. var headerCell = '<th data-tooltip="{0}" style="background-color: transparent; background-image: url(\'{1}\'); \nbackground-repeat: no-repeat; background-attachment: scroll; background-position: center center; background-clip: \nborder-box; background-origin: padding-box; background-size: 60px 60px; cursor: pointer;" colspan="{2}" class="icon" onclick="ajaxHandlerCall(\'{3}\');return false;">&nbsp;</th>';
  2936. var headerRow = '<thead><tr class="header_row">\n <th class="city_name">{0}</th>\n <th data-tooltip="{1}" class="action_points icon actionpointImage"></th>\n <th></th>\n {2}\n</tr></thead>';
  2937. var buildingCell = '<td class="building {0}" data-tooltip="dynamic"></td>';
  2938. var buildingRow = '<tr id="building_{0}">\n <td class="city_name"><img><span class="clickable"></span><sub></sub></td>\n <td class="action_points">\n <td class="sitractions">\n <div class="transport"></div>\n <div class="deploymentfleet"></div>\n <div class="deploymentarmy"></div>\n </td>\n {1}\n</tr>';
  2939. var counts = database.getBuildingCounts;
  2940. var buildingOrder = (database.settings.compressedBuildingList.value ? Constant.altBuildingOrder : Constant.buildingOrder);
  2941. return Utils.format(table, [getHead(), getBody()]);
  2942.  
  2943. function getHead() {
  2944. var headerCells = '';
  2945. var colgroup = '<colgroup span="3"></colgroup>';
  2946. for(var category in buildingOrder) {
  2947. var cols = '';
  2948. $.each(buildingOrder[category], function(index, value) {
  2949.  
  2950. if(value == 'colonyBuilding') {
  2951. if(!database.settings.compressedBuildingList.value || !counts[value]) {
  2952. return true;
  2953. }
  2954. cols += '<col span="' + counts[value] + '">';
  2955. headerCells += Utils.format(headerCell, [database.getGlobalData.getLocalisedString(Constant.Buildings.PALACE) + '/' + database.getGlobalData.getLocalisedString(Constant.Buildings.GOVERNORS_RESIDENCE), Constant.BuildingData[Constant.Buildings.PALACE].icon, counts[value], "?view=buildingDetail&helpId=1&buildingId=" + Constant.BuildingData.palace.buildingId])
  2956. } else if(value == 'productionBuilding') {
  2957. if(!database.settings.compressedBuildingList.value || !counts[value]) {
  2958. return true;
  2959. }
  2960. cols += '<col span="' + counts[value] + '">';
  2961. headerCells += Utils.format(headerCell, [database.getGlobalData.getLocalisedString(Constant.Buildings.WINERY) + '/' + database.getGlobalData.getLocalisedString(Constant.Buildings.STONEMASON) + '/' + database.getGlobalData.getLocalisedString(Constant.Buildings.ALCHEMISTS_TOWER) + '/' + database.getGlobalData.getLocalisedString(Constant.Buildings.GLASSBLOWER), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAUCAMAAACknt2MAAABelBMVEUAAADp49mgkICxmnzVuIxMcwtciQ90pSC/tKR7aFWOfGmIdmPKr4lomxChyk/YxKjTyrzl2slrVkKBblu5ooXp0a3NwrOqm4uNeWRTMzMnGRZFQBvb0sS0p5j18OiTgW3cvpSeXF07JSSJUlLFeHY2NhZzrRKZh3XmyJwPCgl7jzSHyBXlx53EuateSje0amp0YE2Fc2FzSEeFqzfoyJftylO7l1312oXv0GzWyqzN0MH15b311WO3iy2jchyLXiuZrqtyt9uJx+bP2M789+/sz3nv2p7+5IOXZRWHVA/jxou7vquTyuS7x72MqKmEw+J/wOFdk6ylsaXsz6Xz1njKnzTBlkF6SAvhvE2TsraVzeiNyeZ8ttJ7v+EzXnXJ1M2tfiKts6S63ex2utyUw9hFhqV6ss2W0O7fvmDUrUJnnrOk0+tjq8602uzO6fbCyr7Eu6BqrM1tstS74fKbzeXS6/dvud7OrG1PlLeMwNfW7viu2e2i0ObK4OYudx14AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAAAEgAAABIAEbJaz4AAAFfSURBVCgVBcFLTlNhGADQ8/29t/e/reVhChWkUDFRE0hM1IlxYiIzhy5EN+ASTNyBO3DoIpw7VBNAiga0QFKsPK7nBBARV4AiIq4ukUBWVd0bQI0OJJjPC3VcV0AVTdOGhKVot//0TEFR9pebWQ8J1d9qNjxZjhGKYV3XI7N7JLDfU+dh48HmekrKcjYab0m2Y7GeP9tb2ztCL5meT8J45UJre5KOrlZv/hr0TyeXk3p6sdBqfc96439p399GXdx2Pbxv47zTreeiGcxKAABF8aiA/tZjAZ5EfAYA0ALDFKsrB4Cn63sgwbOyVeYu4HnOL0BgJyJOFkR88jIiIiI+ouDVecfhMCIa5iLix1oEJDtnnShmZ2mcT8k5VXdzzpB20kn/8HJkcfVnw4c8V09znr5GSpsbX5qlruOvA7zZbbdXqvJWhfR799tgduzhnVY9z/vtnN9VdfvgLQAAAPgPmQZaHvndsJEAAAAASUVORK5CYII=', counts[value], "?view=ikipedia&helpId=6"]).replace('60px 60px','38px 28px')
  2962. } else if(counts[value]) {
  2963. cols += '<col span="' + counts[value] + '">';
  2964. headerCells += Utils.format(headerCell, [database.getGlobalData.getLocalisedString(value), Constant.BuildingData[value].icon, counts[value], "?view=buildingDetail&helpId=1&buildingId=" + Constant.BuildingData[value].buildingId])
  2965. }
  2966. });
  2967. if(cols != '') {
  2968. colgroup += '<colgroup>' + cols + '</colgroup>'
  2969. }
  2970. }
  2971. return colgroup + Utils.format(headerRow, [database.getGlobalData.getLocalisedString("cities"), database.getGlobalData.getLocalisedString("ActionPoints"), headerCells])
  2972. }
  2973.  
  2974. function getBody() {
  2975. var body = '';
  2976. $.each(database.cities, function(cityId, city) {
  2977. var rowCells = '';
  2978. for(var category in buildingOrder) {
  2979. $.each(buildingOrder[category], function(index, value) {
  2980. if((value == 'productionBuilding' || value == 'colonyBuilding' ) && !database.settings.compressedBuildingList.value) return false;
  2981. var i = 0;
  2982. while(i < counts[value]) {
  2983. var cssClass = '';
  2984. if(value == 'colonyBuilding') {
  2985. cssClass = city.isCapital ? Constant.Buildings.PALACE : Constant.Buildings.GOVERNORS_RESIDENCE
  2986. } else if(value == 'productionBuilding') {
  2987. switch(city.getTradeGoodID) {
  2988. case 1:
  2989. cssClass = Constant.Buildings.WINERY;
  2990. break;
  2991. case 2:
  2992. cssClass = Constant.Buildings.STONEMASON;
  2993. break;
  2994. case 3:
  2995. cssClass = Constant.Buildings.GLASSBLOWER;
  2996. break;
  2997. case 4:
  2998. cssClass = Constant.Buildings.ALCHEMISTS_TOWER;
  2999. break;
  3000. }
  3001. } else {
  3002. cssClass = value
  3003. }
  3004. cssClass += +i;
  3005. rowCells += Utils.format(buildingCell, [cssClass]);
  3006. i++
  3007. }
  3008. })
  3009. }
  3010. body += Utils.format(buildingRow, [city.getId, rowCells])
  3011. });
  3012. return body
  3013. }
  3014. },
  3015. AddIslandCSS : function() {
  3016. if(!(/.*view=island.*/.test(window.document.location))) //&& (ikariam.GameVersion() != undefined)
  3017. if(!this.cssResLoaded()) Utils.addStyleSheet('@import "http://' + ikariam.Host() + '/skin/compiled-' + ikariam.Nationality() + '-island.css";');
  3018. },
  3019.  
  3020. updateCityArmyCell :function(cityId, type, $node){
  3021. var $row;
  3022. var celllevel = !$node;
  3023. try {
  3024. if(celllevel) {
  3025. $row = this.getArmyRow(cityId);
  3026. $node = Utils.getClone($row);
  3027. }
  3028. var city = database.getCityFromId(cityId);
  3029. var data1 = city.military.getUnits.getUnit(type) || 0;
  3030. var data2 = city.military.getIncomingTotals[type] || 0;
  3031. var data3 = city.military.getTrainingTotals[type] || 0;
  3032. var cells = $node.find('td.' + type);
  3033. cells.get(0).textContent = Utils.FormatNumToStr(data1, false, 0) || '';
  3034. cells = cells.eq(1).children('span');
  3035. cells.get(0).textContent = Utils.FormatNumToStr(data2, true, 0) || '';
  3036. cells.get(1).textContent = Utils.FormatNumToStr(data3, true, 0) || '';
  3037. delete this.cityRows.army[cityId];
  3038. if (celllevel){
  3039. Utils.setClone($row, $node);
  3040. this.setArmyTotals(undefined, type);
  3041. }
  3042. } catch(e) {
  3043. SITR.error('updateCityArmyCell', e);
  3044. } finally {
  3045.  
  3046. }
  3047. },
  3048. updateCityArmyRow: function(cityId, $node) {
  3049. var $row;
  3050. var rowLevel = !$node;
  3051. if(rowLevel) {
  3052. $row = this.getArmyRow(cityId);
  3053. $node = Utils.getClone($row);
  3054. }
  3055. for(var armyId in Constant.UnitData) {
  3056. this.updateCityArmyCell(cityId, armyId, $node)
  3057. }
  3058.  
  3059. if(rowLevel) {
  3060. Utils.setClone($row, $node);
  3061. this.setArmyTotals();
  3062. delete this.cityRows.army[cityId];
  3063. }
  3064. },
  3065. updateCitiesArmyData :function(){
  3066. var $node = $('#ArmyTab').find('table.army');
  3067. var $clone = Utils.getClone($node);
  3068. for (var cityId in database.cities){
  3069. SITR.time(this.updateCityArmyRow.bind(this, cityId,$clone.find("#army_" + cityId)), 'updateArmyRow');
  3070. }
  3071. this.setArmyTotals($clone);
  3072. Utils.setClone($node, $clone);
  3073. this.cityRows.army = {};
  3074. },
  3075.  
  3076. updateChangesForCityMilitary : function(cityId, changes) {
  3077. if (changes && changes.length < 5){
  3078. $.each(changes, function(index, unit) {
  3079. this.updateCityArmyCell(cityId,unit)
  3080. }.bind(render));
  3081. this.setArmyTotals();
  3082. } else {
  3083. this.updateCityArmyRow(cityId)
  3084. }
  3085.  
  3086. //Todo
  3087. //render.setAllArmyData()
  3088. },
  3089. updateGlobalData : function(changes) {
  3090. // var pop, research, finance;
  3091. // for (var key in changes) {
  3092. // switch (key) {
  3093. // case 'government':
  3094. // case 'research':
  3095. // case 'finance':
  3096. // default :
  3097. //
  3098. // }
  3099. // }
  3100. this.setAllResourceData();
  3101. return true;
  3102. //Todo: implement update pushed from globaldata changes
  3103. },
  3104. updateMovementsForCity : function(changedCityIds) {
  3105. if(changedCityIds.length)
  3106. $.each(changedCityIds, function(index, id) {
  3107. var city = database.getCityFromId(id);
  3108. if(city) {
  3109. this.setMovementDataForCity(city)
  3110. }
  3111. }.bind(render))
  3112. },
  3113. updateResourcesForCity : function(cityId, changes) {
  3114. var city = database.getCityFromId(cityId);
  3115. if(city) {
  3116. //Todo:Write this. Single resource updates from changes
  3117. events.scheduleAction(this.updateResourceCounters.bind(render, true), 0);
  3118. // $.each(changes, function (index, resourceName) {
  3119. // this.SetAllResourceData(cityId);
  3120. // })
  3121. }
  3122. },
  3123. updateCityDataForCity : function(cityId, changes) {
  3124. var city = database.getCityFromId(cityId);
  3125. if(city) {
  3126. var research = 0, population = 0, finance = 0;
  3127. for(var key in changes) {
  3128. switch(key) {
  3129. case 'research' :
  3130. research += changes[key];
  3131. break;
  3132. case 'priests':
  3133. if(Constant.Government.THEOCRACY === database.getGovernmentType) {
  3134. population += changes[key];
  3135. }
  3136. break;
  3137. case 'culturalGoods':
  3138. research += changes[key];
  3139. population += changes[key];
  3140. break;//todo add democracy only refresh
  3141. case 'citizens':
  3142. case 'population':
  3143. population += changes[key];
  3144. finance += changes[key];
  3145. break;
  3146. case 'name':
  3147. this.setCityName(city);
  3148. break;
  3149. case 'islandId':
  3150. break;
  3151. case 'coordinates':
  3152. break;
  3153. case 'finance':
  3154. finance += changes[key]
  3155. }
  3156. }
  3157. if(!!population) {
  3158. this.setPopulationData(city)
  3159. }
  3160. if(!!research) {
  3161. this.setResearchData(city)
  3162. }
  3163. if(!!finance) {
  3164. this.setFinanceData(city)
  3165. }
  3166. }
  3167. },
  3168. setArmyTotals : function($node, unitId) {
  3169. var data = database.getArmyTotals;
  3170. if(!$node) {
  3171. $node = $('#ArmyTab');
  3172. }
  3173. if(unitId) {
  3174. $node.find('td.total.' + unitId).eq(0).text(Utils.FormatNumToStr(data[unitId].total,false,0) ||'' )
  3175. .next().children('span').eq(0).text(Utils.FormatNumToStr(data[unitId].incoming,true,0) ||'' )
  3176. .next().text(Utils.FormatNumToStr(data[unitId].training,true,0) || '' );
  3177. if(data[unitId].training || data[unitId].incoming || data[unitId].total || database.settings.fullArmyTable.value) {
  3178. $node.find('td.' + unitId+' ,th.' + unitId).show()
  3179. } else {
  3180. $node.find('td.' + unitId+' ,th.' + unitId).hide();
  3181. }
  3182. } else {
  3183. $.each(Constant.UnitData, function(unit, info) {
  3184. $node.find('td.total.' + unit).eq(0).text(Utils.FormatNumToStr(data[unit].total,false,0) ||'' )
  3185. .next().children('span').eq(0).text(Utils.FormatNumToStr(data[unit].incoming,true,0) ||'' )
  3186. .next().text(Utils.FormatNumToStr(data[unit].training,true,0) || '' );
  3187. if(data[unit].training || data[unit].incoming || data[unit].total || database.settings.fullArmyTable.value) {
  3188. $node.find('td.' + unit+' ,th.' + unit).show();
  3189. } else {
  3190. $node.find('td.' + unit+' ,th.' + unit).hide();
  3191. }
  3192. });
  3193. }
  3194. },
  3195. updateChangesForCityBuilding : function(cityID, changes) {
  3196. try {
  3197. var city = database.getCityFromId(cityID);
  3198. if(city) {
  3199. if(changes.length) {
  3200. $.each(changes, function(key, data) {
  3201. var building = city.getBuildingFromPosition(data.position);
  3202. if(building.getName === data.name) {
  3203. this.updateCityBuildingPosition(city, data.position)
  3204. } else {
  3205. this.updateCityBuildingRow(city);
  3206. return false
  3207. }
  3208. }.bind(render))
  3209. }
  3210. }
  3211. } catch(e) {
  3212. SITR.error('updateChangesForCityBuilding', e);
  3213. } finally {
  3214. }
  3215. },
  3216. updateCityBuildingPosition: function(city, position, $node) {
  3217. var building = city.getBuildingFromPosition(position);
  3218. var idx = 0;
  3219. var cellOnly = ($node == undefined);
  3220. $.each(city.getBuildingsFromName(building.getName), function (index, b) {
  3221. if (b.getPosition == building.getPosition) {
  3222. idx = index;
  3223. return false;
  3224. }
  3225. });
  3226. var cell;
  3227. if (cellOnly) {
  3228. $node = render.getBuildingsRow(city);
  3229. cell = $node.find('td.building.' + building.getName + idx)
  3230. }
  3231. else{
  3232. cell = $node.find('td.building.' + building.getName + idx)
  3233. }
  3234. if (!building.isEmpty) {
  3235. if (cell.length) {
  3236. cell.html('<span>' + building.getLevel + '</span>').find('span')
  3237. .removeClass('upgrading upgradable upgradableSoon maxLevel')
  3238. .addClass('clickable')
  3239. .addClass((building.isMaxLevel ? 'maxLevel' : '') + ( building.isUpgrading ? ' upgrading' : '') + (building.isUpgradable ? (city.isUpgrading ? ' upgradableSoon' : ' upgradable') : ''));
  3240. }
  3241. else{
  3242. return false
  3243. }
  3244. }
  3245. return true
  3246. },
  3247. updateCityBuildingRow : function(city, $node) {
  3248. try {
  3249. var $row;
  3250. var cellLevel = !$node;
  3251. if(cellLevel) {
  3252. $row = this.getBuildingsRow(city);
  3253. $node = Utils.getClone($row);
  3254. }
  3255. var success = true;
  3256. $.each(city.getBuildings, function(position, building) {
  3257. success = this.updateCityBuildingPosition(city, position, $node);
  3258. return success
  3259. }.bind(render));
  3260.  
  3261. if (cellLevel){
  3262. render.cityRows.building[city.getId] = undefined;
  3263. $node.find('table.buildings').html(render.getBuildingTable);
  3264.  
  3265. if (!success){
  3266. render.updateCitiesBuildingData();
  3267. $.each(database.cities, function (cityId, city) {
  3268. render.setCityName(city);
  3269. });
  3270. return success;
  3271. }
  3272. Utils.setClone($row, $node);
  3273. }
  3274. return success
  3275. } catch(e) {
  3276. SITR.error('updateCityBuildingRow', e);
  3277. } finally {
  3278. }
  3279.  
  3280. },
  3281. updateCitiesBuildingData : function($redraw) {
  3282. try {
  3283. var success = true;
  3284. var i = 0;
  3285. var $node = $('#BuildTab').find('table.buildings');
  3286. var $clone = $redraw || Utils.getClone($node);
  3287. $.each(database.cities, function(cityId, city){
  3288. success = SITR.time(this.updateCityBuildingRow.bind(this, city, $clone.find('#building_' + city.getId)), 'updateBuildingRow');
  3289. return success
  3290. }.bind(render));
  3291. if (!success){
  3292. $clone.html(render.getBuildingTable);
  3293. if (!$redraw){
  3294. render.updateCitiesBuildingData($clone);
  3295. }
  3296. }
  3297. if (!$redraw){
  3298. this.cityRows.building = {};
  3299. Utils.setClone($node, $clone);
  3300. }
  3301. else {
  3302. $.each(database.cities, function (cityId, city) {
  3303. render.setCityName(city);
  3304. })
  3305. }
  3306. } catch(e) {
  3307. SITR.error('updateCitiesBuildingData', e)
  3308. } finally {
  3309. }
  3310. },
  3311. redrawSettings:function () {
  3312. $('#SettingsTab').html(render.getSettingsTable());
  3313. $("#SITR_Reset_Button").button({icons: {primary: "ui-icon-alert"}, text: true});
  3314. $("#SITR_Website_Button").button({icons: {primary: "ui-icon-home"}, text: true});
  3315. $("#SITR_Update_Button").button({icons: {primary: "ui-icon-info"}, text: true});
  3316. $("#SITR_Bug_Button").button({icons: {primary: "ui-icon-notice"}, text: true});
  3317. },
  3318. DrawContentBox : function() {
  3319. var that = this;
  3320. if(!this.mainContentBox) {
  3321. $("#container").after('<div id="SITRBoard" class="ui-widget" style="display:none;z-index:' + (database.settings.onTop.value ? 65112 : 61) + ';position: absolute; left:70px;top:180px;">\
  3322. <div id="SITR_Tabs">\
  3323. <ul>\
  3324. <li><a href="#ResTab">' + database.getGlobalData.getLocalisedString("Economy") + '</a></li>\
  3325. <li><a href="#BuildTab">Buildings</a></li>\
  3326. <li><a href="#ArmyTab">' + database.getGlobalData.getLocalisedString("Military") + '</a></li>\
  3327. <li><a href="#SettingsTab"><span class="ui-icon ui-icon-gear"/></a></li>\
  3328. <li><a href="#HelpTab"><span class="ui-icon ui-icon-help"/></a></li>\
  3329. </ul>\
  3330. <div id="ResTab"></div>\
  3331. <div id="BuildTab"></div>\
  3332. <div id="ArmyTab"></div>\
  3333. <div id="SettingsTab"></div>\
  3334. <div id="HelpTab"></div>\
  3335. </div>\
  3336. </div>');
  3337. this.mainContentBox = $("#SITRBoard");
  3338. this.$tabs = $("#SITR_Tabs").tabs({collapsible: true, show: null, selected: -1 });
  3339. this.mainContentBox.draggable({
  3340. handle: '#SITR_Tabs > ul',
  3341. cancel: 'div.ui-tabs-panel',
  3342. stop : function() {
  3343. render.SaveDisplayOptions();
  3344. }
  3345. });
  3346. this.$tabs.find('ul li a').on('click', function() {
  3347. events(Constant.Events.TAB_CHANGED).pub(render.$tabs.tabs('option', 'active'));
  3348. render.SaveDisplayOptions();
  3349. });
  3350. render.mainContentBox.on('mouseenter',function() {
  3351. if(database.settings.windowTennis.value) {
  3352. render.mainContentBox.css('z-index', "65112")
  3353. }
  3354. }).on('mouseleave', function() {
  3355. if(database.settings.windowTennis.value) {
  3356. render.mainContentBox.css('z-index', "2")
  3357. }
  3358. })
  3359. }
  3360. },
  3361. AttachClickHandlers : function() {
  3362. $('body').on('click', '#js_buildingUpgradeButton', function(e) {
  3363.  
  3364. var href = this.getAttribute('href');
  3365. if(href !== '#') {
  3366. var params = $.decodeUrlParam(href);
  3367. if(params['function'] === "upgradeBuilding") {
  3368. var upgradeSuccessCheck = (function upgradeSuccess() {
  3369. var p = params;
  3370. return function(response) {
  3371. var len = response.length;
  3372. var feedback = 0;
  3373. while(len--) {
  3374. if(response[len][0] == 'provideFeedback') {
  3375. feedback = response[len][1][0].type;
  3376. break;
  3377. }
  3378. }
  3379. if(feedback == 10) { //success
  3380. render.updateChangesForCityBuilding(p['cityId'] || ikariam.getCurrentCity, [])
  3381. }
  3382. events('ajaxResponse').unsub(upgradeSuccessCheck);
  3383. }
  3384. })();
  3385. }
  3386. events('ajaxResponse').sub(upgradeSuccessCheck)
  3387. }
  3388. });
  3389.  
  3390. //Global click handlers
  3391. render.mainContentBox.on('click', 'td.city_name span.clickable',function(event) {
  3392. var target = $(event.target);
  3393. var city = database.getCityFromId(target.parents('tr').attr('id').split('_').pop());
  3394. var classes = target.parents('td').attr('class');
  3395. var params = {cityId: city.getId};
  3396. // city link
  3397. if(!city.isCurrentCity) {
  3398. $("#js_cityIdOnChange").val(city.getId);
  3399. if(unsafeWindow.ikariam.templateView) {
  3400. if(unsafeWindow.ikariam.templateView.id === 'tradegood' || unsafeWindow.ikariam.templateView.id === 'resource') {
  3401. params.templateView = unsafeWindow.ikariam.templateView.id;
  3402. if(ikariam.viewIsCity) {
  3403. params.islandId = city.getIslandID;
  3404. params.view = unsafeWindow.ikariam.templateView.id;
  3405. params.type = unsafeWindow.ikariam.templateView.id == 'resource' ? 'resource' : city.getTradeGoodID;
  3406. } else {
  3407. params.currentIslandId = ikariam.getCurrentCity.getIslandID
  3408. }
  3409. }
  3410. }
  3411. ikariam.loadUrl(true, ikariam.mainView, params)
  3412. }
  3413. return false;
  3414. }).on('click', 'td.sitractions div.transport',function(event) {
  3415. var target = $(event.target);
  3416. var city = database.getCityFromId(target.parents('td').parents('tr').attr('id').split('_').pop());
  3417. if(!city.isCurrentCity && ikariam.getCurrentCity) {
  3418. ikariam.loadUrl(true, ikariam.mainView, {view: 'transport', destinationCityId: city.getId, templateView: Constant.Buildings.TRADING_PORT})
  3419. }
  3420. return false;
  3421. }).on('click', 'td.sitractions div[class*=deployment]', function(event) {
  3422. var target = $(event.target);
  3423. var city = database.getCityFromId(target.parents('tr').attr('id').split('_').pop());
  3424. var type = target.attr('class').split(' ').pop().split('deployment').pop();
  3425. if(ikariam.currentCityId === city.getId) {
  3426. return false
  3427. }
  3428. var params = {
  3429. cityId : ikariam.CurrentCityId,
  3430. view : 'deployment',
  3431. deploymentType : type,
  3432. destinationCityId: city.getId
  3433. };
  3434. ikariam.loadUrl(true, null, params)
  3435. });
  3436.  
  3437. //Resource table handlers
  3438. $('#ResTab').on('click', 'span.clickable[class^=current]', function(event) {
  3439. var target = $(event.target);
  3440. var city = database.getCityFromId(target.parents('tr').attr('id').split('_').pop());
  3441. //building link
  3442. var resource = target.parents('td').attr('class').split(' ').pop();
  3443. var params = {
  3444. cityId: city.getId
  3445. };
  3446.  
  3447. if(ikariam.CurrentCityId == city.getId || !ikariam.viewIsIsland) {
  3448. params.type = resource == Constant.Resources.WOOD ? 'resource' : city.getTradeGoodID;
  3449. params.view = resource == Constant.Resources.WOOD ? 'resource' : 'tradegood';
  3450. params.islandId = city.getIslandID;
  3451. } else if(ikariam.viewIsIsland) {
  3452. params.templateView = resource == Constant.Resources.WOOD ? 'resource' : 'tradegood';
  3453. if(unsafeWindow.ikariam.templateView)unsafeWindow.ikariam.templateView.id = null;
  3454. }
  3455.  
  3456. if(ikariam.viewIsIsland) {
  3457. params.currentIslandId = ikariam.getCurrentCity.getIslandID;
  3458. }
  3459.  
  3460. ikariam.loadUrl(true, ikariam.mainView, params);
  3461. render.AddIslandCSS();
  3462. return false;
  3463. });
  3464.  
  3465. //Building table handlers
  3466. $('#SITR_Tabs').on('click', 'td.building span.clickable', function(event) {
  3467. var target = $(event.target);
  3468. var city = database.getCityFromId(target.parents('tr').attr('id').split('_').pop());
  3469. //building link
  3470.  
  3471. var className = target.parents('td').attr('class').split(' ').pop();
  3472. var building = city.getBuildingsFromName(className.slice(0, -1))[className.charAt(className.length - 1)];
  3473. var params = building.getUrlParams;
  3474. if(unsafeWindow.ikariam.templateView)unsafeWindow.ikariam.templateView.id = null;
  3475. ikariam.loadUrl(true, 'city', params);
  3476. return false;
  3477. });
  3478.  
  3479. //Army table handlers
  3480.  
  3481. },
  3482. dynamicTip : function(id, type) {
  3483.  
  3484. var city = database.getCityFromId(id);
  3485. type = type.split(' ');
  3486. if(type[0] == 'dynamic') {
  3487. type = type.splice(1)
  3488. } else return type.join(' ');
  3489. var a = type[0];
  3490. var b = type[1];
  3491. if(a == 'resource') {
  3492. //b == cell type
  3493. var resourceName = type[2];
  3494. if(b == 'current') {
  3495. return ''
  3496. }
  3497. if(b == 'income') {
  3498. if(resourceName !== city.getTradeGood && resourceName !== Constant.Resources.WOOD) {
  3499. return ''
  3500. }
  3501. return getIncomeTip(city.getResource(resourceName).getProduction * 3600, resourceName)
  3502. }
  3503. if(b == 'progress') {
  3504. var prod = city.getResource(resourceName).getProduction * 3600;
  3505. var current = city.getResource(resourceName).getCurrent;
  3506. return getProgressTip(city, resourceName)
  3507. }
  3508. if(b == 'consumption') {
  3509.  
  3510. return (resourceName == Constant.Resources.WINE ? getWineUseTooltip(city.getResource(Constant.Resources.WINE).getConsumption) : '');
  3511. }
  3512. if(b == 'movement') {
  3513. return getMovementTip(database.getGlobalData.getResourceMovementsToCity(id), city.getResource(resourceName).getCurrent, resourceName);
  3514. }
  3515. if(b === 'totals') {
  3516. var totals = {};
  3517. $.each(database.cities, function(cityId, city) {
  3518. $.each(Constant.Resources, function(key, resourceName) {
  3519. var res = city.getResource(resourceName);
  3520. if(!totals[resourceName]) {
  3521. totals[resourceName] = {}
  3522. }
  3523.  
  3524. totals[resourceName].total = totals[resourceName].total ? totals[resourceName].total + res.getCurrent : res.getCurrent;
  3525. totals[resourceName].income = totals[resourceName].income ? totals[resourceName].income + res.getProduction * 3600 - res.getConsumption : res.getProduction * 3600 - res.getConsumption;
  3526.  
  3527. })
  3528. });
  3529.  
  3530. var r = '';
  3531. var finalSums = {income: 0, total: 0, day: 0, week: 0};
  3532. $.each(totals, function(resourceName, data) {
  3533. var day = data.total + data.income * 24;
  3534. var week = data.total + data.income * 168;
  3535. r += Utils.format('<tr>\n <td><div class="icon {0}Image"></div></td>\n <td >{1}</td>\n <td >{2}</td>\n <td >{3}</td>\n <td >{4}</td>\n</tr>', [resourceName, Utils.FormatNumToStr(data.income, false, 0), Utils.FormatNumToStr(data.total, false, 0) , Utils.FormatNumToStr(day, false, 0) , Utils.FormatNumToStr(week, false, 0)]);
  3536. finalSums.income += data.income;
  3537. finalSums.total += data.total;
  3538. finalSums.day += day;
  3539. finalSums.week += week
  3540. });
  3541. if(r === '') {
  3542. return ''
  3543. } else {
  3544. return Utils.format('<table>\n <thead>\n <td></td>\n <td><b>Income</b></td>\n <td ><b>Total</b></td>\n <td ><b>+24hrs</b></td>\n <td ><b>+7days</b></td>\n </thead>\n <tbody>\n {0}\n <tfoot>\n <td></td>\n <td >{1}</td>\n <td >{2}</td>\n <td >{3}</td>\n <td >{4}</td>\n </tfoot>\n </tbody>\n</table>', [r, Utils.FormatNumToStr(finalSums.income, false, 0) , Utils.FormatNumToStr(finalSums.total, false, 0) , Utils.FormatNumToStr(finalSums.day, false, 0) , Utils.FormatNumToStr(finalSums.week, false, 0)])
  3545. }
  3546. }
  3547.  
  3548. } else if(a == 'building') {
  3549. // b == building name
  3550. var bName = type[1]; //building name
  3551. var bLevel = parseInt(type[2]); //building level
  3552. var pos = parseInt(type[3]); //position
  3553. return getBuildingTooltip(database.cities[id]._buildings[pos]);
  3554. } else if(a == 'army') {
  3555. //b == cell type
  3556. var unit = type[2];
  3557. if(b == 'movement') {
  3558. return 'not yet implemented'
  3559. } else if(b == 'training') {
  3560. var table = '<table>\n <thead>\n <td><img src="{0}" style="height: 11px;"></td>\n <td><b>Training</b></td>\n <td></td>\n </thead>\n <tbody>\n{1}\n <tr class="small">\n <td></td>\n <td>{2}</td>\n <td class="left"><i>«Total</i></td>\n </tr>\n </tbody>\n</table>';
  3561. var rows = '';
  3562. var total = 0;
  3563. $.each(city.military.getTrainingForUnit(unit), function(index, data) {
  3564. rows += Utils.format('<tr>\n <td><b>+</b></td>\n <td >{0}</td>\n <td ><i>«{1}</i></td>\n</tr>', [data.count, Utils.FormatTimeLengthToStr(data.time - $.now(), 3)]);
  3565. total += data.count;
  3566. });
  3567.  
  3568. if(rows === '') {
  3569. return ''
  3570. } else {
  3571. return Utils.format(table, [getImage(unit), rows, total])
  3572. }
  3573. }
  3574. }
  3575.  
  3576. },
  3577. startResourceCounters : function() {
  3578. this.stopResourceCounters();
  3579. this.resUpd = events.scheduleActionAtInterval(render.updateResourceCounters.bind(render), 5000);
  3580. this.updateResourceCounters(true);
  3581. },
  3582. stopResourceCounters : function() {
  3583. if(this.resUpd) {
  3584. this.resUpd();
  3585. this.resUpd = null;
  3586. }
  3587. },
  3588. getResourceRow : function(city) {
  3589. return this._getRow(city, "resource")
  3590. },
  3591. getBuildingsRow : function(city) {
  3592. return this._getRow(city, "building")
  3593. },
  3594. getArmyRow : function(city) {
  3595. return this._getRow(city, "army")
  3596. },
  3597. _getRow :function(city, type){
  3598. city = typeof city == 'object'?city:database.getCityFromId(city);
  3599. if(!this.cityRows[type][city.getId])
  3600. this.cityRows[type][city.getId] = $("#" + type + "_" + city.getId);
  3601. return this.cityRows[type][city.getId]
  3602. },
  3603. getAllRowsForCity : function(city) {
  3604. return this.getResourceRow(city).add(this.getBuildingsRow(city)).add(this.getArmyRow(city))
  3605. },
  3606. setCityName : function(city, rows) {
  3607. if(!rows) {
  3608. rows = this.getResourceRow(city).add(this.getBuildingsRow(city)).add(this.getArmyRow(city))
  3609. }
  3610. rows.find('td.city_name').each(function(index, elem) {
  3611. elem.children[0].outerHTML = '<span class="icon ' + city.getTradeGood + 'Image"></span>';
  3612. elem.children[1].textContent = city.getName;
  3613. elem.children[2].textContent = ' ' + (city.getAvailableBuildings || '');
  3614. elem.children[2].setAttribute('data-tooltip', database.getGlobalData.getLocalisedString('free_building_space'));
  3615. });
  3616. },
  3617. setActionPoints : function(city, rows) {
  3618. if(!rows) {
  3619. rows = this.getAllRowsForCity(city);
  3620. }
  3621. rows.find('td.action_points').text(city.getAvailableActions)
  3622. },
  3623. setFinanceData : function(city, row) {
  3624. if(!row) {
  3625. row = this.getResourceRow(city)
  3626. }
  3627. row.find('td.gold_income > span').eq(0).text(Utils.FormatNumToStr(city.getIncome, true, 0)).siblings(0).text(Utils.FormatNumToStr(city.getExpenses, true, 0))
  3628. },
  3629. setPopulationData : function(city, row) {
  3630. if(!row) {
  3631. row = this.getResourceRow(city)
  3632. }
  3633. var populationData = city.populationData;
  3634. var popSpace = Math.floor(populationData.currentPop-populationData.maxPop);
  3635.  
  3636. row.find('td.population span').get(0).textContent = Utils.FormatNumToStr(populationData.currentPop, false, 0);
  3637. row.find('td.population span').get(1).textContent = (popSpace!== 0?Utils.FormatNumToStr(popSpace, true, 0):'');
  3638.  
  3639. var fillperc = 100 / populationData.maxPop * populationData.currentPop ;
  3640. row.find('td.population div.progressbar').find('div.ui-progressbar-value').width(fillperc + "%").removeClass("normal warning almostfull full").addClass(fillperc > 90 ? fillperc > 96 ? "warning" : "normal" : fillperc > 70 ? "almostfull" : "full");
  3641.  
  3642. var img;
  3643. img = populationData.growth > 1 ? (populationData.growth < 6 ? 'happy' : 'ecstatic') : populationData.growth < 0 ? (populationData.growth < -1 ? 'outraged' : 'sad') : 'neutral';
  3644.  
  3645. if(populationData.growth > 1) {
  3646. img = populationData.growth < 6 ? 'happy' : 'ecstatic';
  3647. } else if(populationData.growth < 1) {
  3648. img = populationData.growth < 0 ? populationData.growth < -1 ? 'outraged' : 'sad' : 'neutral';
  3649. }
  3650. img = Utils.format('skin/smilies/{0}_x25.png', [img]);
  3651.  
  3652. row.find('td.population_growth img').attr('src', img);
  3653. row.find('td.population_happiness').get(0).textContent = Utils.FormatNumToStr(populationData.growth, true, 2);
  3654. },
  3655. setResearchData : function(city, row) {
  3656. if(!row) {
  3657. row = this.getResourceRow(city)
  3658. }
  3659.  
  3660. row.find('td.research').get(0).textContent = Math.floor(city.research.getResearch);
  3661. },
  3662. setMovementDataForCity : function(city, row) {
  3663. if(!row) {
  3664. row = this.getResourceRow(city)
  3665. }
  3666. var totalIncoming = {wood: 0, wine: 0, marble: 0, glass: 0, sulfur: 0};
  3667. $.each(city.getIncomingResources, function(index, element) {
  3668. for(var resourceName in Constant.Resources) {
  3669. totalIncoming[Constant.Resources[resourceName]] += element.getResource(Constant.Resources[resourceName]);
  3670. }
  3671. });
  3672. row.find('td.resource.wood').find('span.incoming').get(0).textContent = Utils.FormatNumToStr(totalIncoming[Constant.Resources.WOOD] || ' - ');
  3673. row.find('td.resource.wine').find('span.incoming').get(0).textContent = Utils.FormatNumToStr(totalIncoming[Constant.Resources.WINE] || ' - ');
  3674. row.find('td.resource.marble').find('span.incoming').get(0).textContent = Utils.FormatNumToStr(totalIncoming[Constant.Resources.MARBLE] || ' - ');
  3675. row.find('td.resource.glass').find('span.incoming').get(0).textContent = Utils.FormatNumToStr(totalIncoming[Constant.Resources.GLASS] || ' - ');
  3676. row.find('td.resource.sulfur').find('span.incoming').get(0).textContent = Utils.FormatNumToStr(totalIncoming[Constant.Resources.SULFUR] || ' - ');
  3677. },
  3678. setAllResourceData : function() {
  3679. this.startResourceCounters()
  3680. },
  3681. setCommonData :function(){
  3682. $.each(database.cities, function(cityId, city) {
  3683. this.setCityName(city);
  3684. this.setActionPoints(city);
  3685. }.bind(render))
  3686. },
  3687. updateResourceCounters : function(force) {
  3688. try {
  3689. if((this.$tabs.tabs('option', 'active') == 0 ) || force) {
  3690. var tot = {wood: 0, wine: 0, marble: 0, glass: 0, sulfur: 0};
  3691. var inc = {wood: 0, wine: 0, marble: 0, glass: 0, sulfur: 0};
  3692. var conWine = 0;
  3693. var income = 0;
  3694. var researchCost = 0;
  3695. var researchTot = 0;
  3696.  
  3697. $.each(database.cities, function(cityId, city) {
  3698. var $row = Utils.getClone(this.getResourceRow(city));
  3699. if(force) {
  3700. this.setFinanceData(city, $row);
  3701. this.setPopulationData(city, $row);
  3702. this.setResearchData(city, $row);
  3703. this.setMovementDataForCity(city, $row)
  3704. }
  3705.  
  3706. income += Math.floor(city.getIncome);
  3707. researchTot += city.research.getResearch;
  3708.  
  3709. researchCost += Math.floor(city.getExpenses);
  3710.  
  3711. var storage = city.maxResourceCapacities;
  3712. $.each(Constant.Resources, function(key, resourceName) {
  3713. var currentResource = city.getResource(resourceName);
  3714. var production = currentResource.getProduction * 3600;
  3715. var current = currentResource.getCurrent;
  3716. var consumption = resourceName == Constant.Resources.WINE ? currentResource.getConsumption : 0;
  3717. inc[resourceName] += production;
  3718. tot[resourceName] += current;
  3719. conWine += consumption;
  3720.  
  3721. var rescells = $row.find('td.resource.' + resourceName);
  3722.  
  3723. rescells.find('span.current').addClass((resourceName == Constant.Resources.WOOD || city.getTradeGood == resourceName) ? "clickable" : "").get(0).textContent = (current ? Utils.FormatNumToStr(current, false, 0) : '0');
  3724. rescells.find('span.production').get(0).textContent = (production ? Utils.FormatNumToStr(production, true, 0) : '');
  3725.  
  3726. if(resourceName === Constant.Resources.WINE) {
  3727. rescells.find('span.consumption').get(0).textContent = (consumption ? Utils.FormatNumToStr(0 - consumption, true, 0) : '');
  3728. //Full hours until tavern cant pay wine bill, plus time until next tick (current tick is paid)
  3729. var time = currentResource.getEmptyTime;
  3730. time = time > 1? Math.floor(time) + (60 - new Date().getMinutes())/60 : 0;
  3731. time *= 3600000;
  3732. rescells.find('span.emptytime').removeClass('Red Green').addClass(time > database.settings.wineWarningTime.value * 3600000 ? 'Green' : 'Red').get(0).textContent = (Utils.FormatTimeLengthToStr(time, 2))
  3733. }
  3734. var fillperc = (current / storage.capacity) * 100;
  3735. rescells.find('div.progressbar').find('div.ui-progressbar-value').width(fillperc + "%").removeClass("normal warning almostfull full").addClass(fillperc > 90 ? fillperc > 96 ? "full" : "almostfull" : fillperc > 70 ? "warning" : "normal");
  3736. if(storage.safe > current) {
  3737. rescells.find('span.safeImage').show()
  3738. } else {
  3739. rescells.find('span.safeImage').hide()
  3740. }
  3741.  
  3742. }.bind(render));
  3743. Utils.setClone(this.getResourceRow(city),$row);
  3744. this.cityRows.resource[city.getId] = null
  3745. }.bind(render));
  3746.  
  3747. $("#t_currentwood").get(0).textContent = Utils.FormatNumToStr(Math.round(tot[Constant.Resources.WOOD]), false);
  3748. $("#t_currentwine").get(0).textContent = Utils.FormatNumToStr(Math.round(tot[Constant.Resources.WINE]), false);
  3749. $("#t_currentmarble").get(0).textContent = Utils.FormatNumToStr(Math.round(tot[Constant.Resources.MARBLE]), false);
  3750. $("#t_currentglass").get(0).textContent = Utils.FormatNumToStr(Math.round(tot[Constant.Resources.GLASS]), false);
  3751. $("#t_currentsulfur").get(0).textContent = Utils.FormatNumToStr(Math.round(tot[Constant.Resources.SULFUR]), false);
  3752. $("#t_woodincome").find('span').get(0).textContent = Utils.FormatNumToStr(Math.round(inc[Constant.Resources.WOOD]), true);
  3753. $("#t_wineincome").children('span').eq(0).text(Utils.FormatNumToStr(Math.round(inc[Constant.Resources.WINE]), true)).siblings('span').eq(0).text(Utils.FormatNumToStr(Math.round(conWine), true));
  3754. $("#t_marbleincome").find('span').get(0).textContent = Utils.FormatNumToStr(Math.round(inc[Constant.Resources.MARBLE]), true);
  3755. $("#t_glassincome").find('span').get(0).textContent = Utils.FormatNumToStr(Math.round(inc[Constant.Resources.GLASS]), true);
  3756. $("#t_sulfurincome").find('span').get(0).textContent = Utils.FormatNumToStr(Math.round(inc[Constant.Resources.SULFUR]), true);
  3757.  
  3758. tot = inc = null;
  3759.  
  3760. var expense = database.getGlobalData.finance.armyCost + database.getGlobalData.finance.armySupply + database.getGlobalData.finance.fleetCost + database.getGlobalData.finance.fleetSupply - researchCost;
  3761. var sigmaIncome = income - expense;
  3762. document.getElementById("t_goldincome").children[0].textContent = Utils.FormatNumToStr(sigmaIncome, true, 0);
  3763. document.getElementById("t_goldincome").children[1].textContent = sigmaIncome > 0 ? '\u221E' : Utils.FormatTimeLengthToStr((database.getGlobalData.finance.currentGold / sigmaIncome) * 60 * 60 * 1000, true, 0);
  3764. document.getElementById("t_research").textContent = researchTot ? Utils.FormatNumToStr(researchTot, true, 0) : ' - ';
  3765.  
  3766. }
  3767. } catch(e) {
  3768. SITR.error('UpdateResourceCounters', e)
  3769. }
  3770. }
  3771. };
  3772.  
  3773. function getCityNameFromID(originCity) {
  3774. var ret = '';
  3775. try {
  3776. ret = database.cities[parseInt(originCity)].getName
  3777. } catch(e) {
  3778. ret = originCity;
  3779. }
  3780. return ret;
  3781. }
  3782.  
  3783. render.LoadCSS = function() {
  3784. //Main Css
  3785. GM_addStyle('/* Global board styles */\n#SITRBoard .clickable {\n color: #542c0f;\n font-weight: 700; }\n#SITRBoard .clickable:hover {\n cursor: pointer;\n text-decoration: underline; }\n#SITRBoard .Bold, #SITRBoard .Red, #SITRBoard .Blue, #SITRBoard .Green {\n font-weight: bold; }\n#SITRBoard .Green {\n color: green !important; }\n#SITRBoard .Red {\n color: red !important; }\n#SITRBoard .Blue {\n color: blue !important; }\n#SITRBoard .icon {\n background-clip: border-box;\n background-repeat: no-repeat;\n background-position: center;\n background-color: transparent;\n background-size: auto 20px; }\n#SITRBoard .safeImage {\n background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAJCAYAAAD+WDajAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEFJREFUeNpi/P//PwMIhOrzQhhAsPriZ0YQzYQugcxnQhaE6YABxhA9HhRdyICJAQ/AayzxOtFdzYRuFLIVAAEGANwqFwuukYKqAAAAAElFTkSuQmCC");\n background-size: auto auto !important; }\n#SITRBoard .transportImage {\n background-image: url(skin/actions/transport.jpg); }\n#SITRBoard .tradeImage {\n background-image: url(skin/actions/trade.jpg); }\n#SITRBoard .merchantImage {\n background-image: url(skin/minimized/merchantNavy.png);\n background-position: 0 -5px; }\n#SITRBoard .woodImage {\n background-image: url(skin/resources/icon_wood.png); }\n#SITRBoard .wineImage {\n background-image: url(skin/resources/icon_wine.png); }\n#SITRBoard .marbleImage {\n background-image: url(skin/resources/icon_marble.png); }\n#SITRBoard .sulfurImage {\n background-image: url(skin/resources/icon_sulfur.png); }\n#SITRBoard .glassImage {\n background-image: url(skin/resources/icon_glass.png); }\n#SITRBoard .researchImage {\n background-image: url(skin/layout/bulb-on.png); }\n#SITRBoard .populationImage {\n background-image: url(skin/resources/icon_population.png); }\n#SITRBoard .goldImage {\n background-image: url(skin/resources/icon_gold.png); }\n#SITRBoard .happyImage {\n background-image: url(skin/smilies/happy.png); }\n#SITRBoard .actionpointImage {\n background-image: url(skin/resources/icon_actionpoints.png); }\n#SITRBoard .growthImage {\n background-image: url(skin/icons/growth_positive.png); }\n#SITRBoard .scientistImage {\n background-image: url(skin/characters/40h/scientist_r.png); }\n#SITRBoard .priestImage {\n background-image: url(skin/characters/40h/templer_r.png); }\n#SITRBoard .citizenImage {\n background-image: url(skin/characters/40h/citizen_r.png); }\n#SITRBoard .cityIcon {\n background-image: url(skin/icons/city_30x30.png); }\n#SITRBoard .governmentIcon {\n background-image: url(skin/government/zepter_20.png); }\n#SITRBoard .researchIcon {\n background-image: url(skin/icons/researchbonus_30x30.png); }\n#SITRBoard .tavernIcon {\n background-image: url(skin/buildings/tavern_30x30.png); }\n#SITRBoard .culturalIcon {\n background-image: url(skin/interface/icon_message_write.png); }\n#SITRBoard .museumIcon {\n background-image: url(skin/buildings/museum_30x30.png); }\n#SITRBoard .incomeIcon {\n background-image: url(skin/icons/income_positive.png); }\n#SITRBoard .crownIcon {\n background-image: url(skin/layout/crown.png); }\n#SITRBoard .corruptionIcon {\n background-image: url(skin/icons/corruption_24x24.png); }\n#SITRBoard #SITRTip {\n display: none;\n position: absolute;\n top: 0;\n left: 0;\n z-index: 99999999; }\n#SITRBoard #SITRTip .icon {\n background-clip: border-box;\n background-repeat: no-repeat;\n background-position: 0;\n background-color: transparent;\n background-attachment: scroll;\n background-size: 25px auto;\n height: 17px;\n min-width: 24px;\n width: 24px; }\n#SITRBoard #SITRTip .content {\n background-color: #fae0ae;\n border: 1px solid #e4b873;\n position: relative;\n overflow: hidden;\n text-align: left;\n word-wrap: break-word; }\n#SITRBoard #SITRTip .content table {\n width: 100%; }\n#SITRBoard #SITRTip .content table tr.data {\n background-color: #faeac8; }\n#SITRBoard #SITRTip .content table tr.total {\n background-color: #fae0ae; }\n#SITRBoard #SITRTip .content table td {\n padding: 2px;\n height: auto !important;\n text-align: right; }\n#SITRBoard #SITRTip .content table th {\n padding: 2px;\n height: auto !important;\n text-align: center;\n font-weight: bold; }\n#SITRBoard #SITRTip .content table tbody td:last-child {\n text-align: left;\n white-space: nowrap;\n font-style: italic; }\n#SITRBoard #SITRTip .content table tfoot {\n border-top: 3px solid #fdf7dd; }\n#SITRBoard #SITRTip .content table tfoot td:last-child {\n text-align: left;\n white-space: nowrap;\n font-style: italic; }\n#SITRBoard #SITRTip .content table thead {\n background: #f8e7b3; }\n#SITRBoard #SITRTip .content table thead th.lf {\n border-left: 2px solid #e4b873; }\n#SITRBoard #SITRTip .content table tbody td.lf {\n border-left: 2px solid #e4b873; }\n#SITRBoard #SITRTip .content table th.nolf, #SITRBoard #SITRTip .content table td.nolf {\n border-left: none; }\n#SITRBoard #SITRTip .content th.lfdash, #SITRBoard #SITRTip .content td.lfdash {\n border-left: 1px dashed #e4b873; }\n#SITRBoard #SITRTip .content table tr.small td {\n height: auto !important;\n padding-top: 1px;\n font-size: 10px !important;\n line-height: 11px !important; }\n#SITRBoard #SITR_Tabs table {\n width: 100% !important;\n text-align: center;\n border: 2px solid #ffffff; }\n#SITRBoard #SITR_Tabs table colgroup {\n border-left: 2px solid #e4b873; }\n#SITRBoard #SITR_Tabs table colgroup:first-child {\n border: none !important; }\n#SITRBoard #SITR_Tabs table colgroup col {\n border-left: 1px dashed #e4b873; }\n#SITRBoard #SITR_Tabs table thead {\n background: #f8e7b3 url(skin/input/button.png) repeat-x scroll 0 bottom; }\n#SITRBoard #SITR_Tabs table thead tr {\n height: 30px; }\n#SITRBoard #SITR_Tabs table thead tr th {\n text-align: center;\n font-weight: bold;\n text-shadow: 0 0.12em #FFFFFF;\n overflow: hidden;\n white-space: nowrap; }\n#SITRBoard #SITR_Tabs table thead tr th.icon {\n min-width: 30px;\n background-size: auto 20px; }\n#SITRBoard #SITR_Tabs table tbody tr {\n border-top: 1px solid #e4b873; }\n#SITRBoard #SITR_Tabs table tbody tr:nth-child(even) {\n background-color: #f6ebba; }\n#SITRBoard #SITR_Tabs table tbody tr.selected {\n background-color: #FAE3B8;\n box-shadow: 0 0 1em #CB9B6A inset; }\n#SITRBoard #SITR_Tabs table tbody tr:hover {\n background-color: #fff;\n box-shadow: 0 0 1em #CB9B6A; }\n#SITRBoard #SITR_Tabs table tbody tr td.city_name {\n width: 110px;\n max-width: 110px;\n padding-left: 3px;\n text-align: left;\n padding-right: 14px; }\n#SITRBoard #SITR_Tabs table tbody tr td.city_name span.icon {\n background-repeat: no-repeat;\n float: left;\n width: 20px;\n background-size: 20px auto;\n margin: 0 2px 0 -1px;\n height: 16px;\n cursor: move; }\n#SITRBoard #SITR_Tabs table tbody tr td.sitractions div {\n background-clip: border-box;\n background: transparent repeat scroll 0 0;\n background-size: 25px auto;\n height: 17px;\n min-width: 24px;\n width: 24px; }\n#SITRBoard #SITR_Tabs table tbody tr td.sitractions div.transport {\n background-image: url("skin/actions/transport.jpg"); }\n#SITRBoard #SITR_Tabs table tbody tr td.sitractions div.deploymentarmy {\n background-image: url("skin/actions/move_army.jpg");\n float: left; }\n#SITRBoard #SITR_Tabs table tbody tr td.sitractions div.deploymentfleet {\n background-image: url("skin/actions/move_fleet.jpg");\n float: right; }\n#SITRBoard #SITR_Tabs table tbody tr td.sitractions div:hover {\n background-position: 0 -17px; }\n#SITRBoard #SITR_Tabs table tbody tr.selected .sitractions div, #SITRBoard #SITR_Tabs table tbody tr.current .sitractions div {\n background-position: 0 16px; }\n#SITRBoard #SITR_Tabs table tfoot {\n background: #fae0ae;\n background: #e7c680 url(skin/input/button.png) repeat-x scroll 0 0;\n border-top: 2px solid #e4b873; }\n#SITRBoard #SITR_Tabs table tfoot tr td {\n text-align: right;\n text-shadow: 0 0.12em #FFFFFF; }\n#SITRBoard #SITR_Tabs table tfoot tr td.total {\n text-align: right; }\n#SITRBoard #SITR_Tabs table tfoot tr td.total span {\n line-height: 1em;\n height: 1em;\n font-size: 0.8em;\n display: block; }\n#SITRBoard #SITR_Tabs table tfoot tr td#t_sigma, #SITRBoard #SITR_Tabs table tfoot tr td.sigma {\n font-weight: 700;\n text-align: center; }\n#SITRBoard #ResTab div.progressbar .normal {\n background: #73443E; }\n#SITRBoard #ResTab div.progressbar .warning {\n background: #8F1D1A; }\n#SITRBoard #ResTab div.progressbar .almostfull {\n background: #B42521; }\n#SITRBoard #ResTab div.progressbar .full {\n background: #ff0000; }\n#SITRBoard #ResTab table tr td.gold_income, #SITRBoard #ResTab table tr td.resource, #SITRBoard #ResTab table tr td.army:nth-child(even) {\n text-align: right; }\n#SITRBoard #ResTab table tr td.gold_income span, #SITRBoard #ResTab table tr td.resource span, #SITRBoard #ResTab table tr td.army:nth-child(even) span {\n line-height: 1em;\n height: 1em;\n font-size: 0.8em;\n display: block; }\n#SITRBoard #ResTab table tr td.gold_income span.icon, #SITRBoard #ResTab table tr td.resource span.icon, #SITRBoard #ResTab table tr td.army:nth-child(even) span.icon {\n background-repeat: no-repeat;\n float: left;\n width: 7px;\n height: 9px;\n padding: 5px 4px 0 0; }\n#SITRBoard #ResTab table tr td.gold_income span.current, #SITRBoard #ResTab table tr td.resource span.current, #SITRBoard #ResTab table tr td.army:nth-child(even) span.current {\n font-size: 1em;\n display: inline; }\n#SITRBoard #ResTab table tr td.population {\n text-align: right; }\n#SITRBoard #ResTab table tr td.population span:nth-child(2) {\n line-height: 1em;\n height: 1em;\n font-size: 0.8em;\n display: block; }\n#SITRBoard #BuildTab table tbody tr td {\n background-clip: border-box;\n background-repeat: no-repeat;\n background-position: center;\n background-color: transparent;\n background-size: auto 20px; }\n#SITRBoard #BuildTab table tbody tr td span.maxLevel {\n color: rgba(84, 44, 15, 0.3); }\n#SITRBoard #BuildTab table tbody tr td span.upgradableSoon {\n color: #4169e1;\n font-style: italic; }\n#SITRBoard #BuildTab table tbody tr td span.upgradable {\n color: green;\n font-style: italic; }\n#SITRBoard #BuildTab table tbody tr td span.upgradable:after {\n content: "+"; }\n#SITRBoard #BuildTab table tbody tr td span.upgrading {\n background: url("/skin/icons/arrow_upgrade.png") no-repeat scroll 1px 3px transparent;\n border-radius: 5px 5px 5px 5px;\n box-shadow: 0 0 2px rgba(0, 0, 0, 0.8);\n display: inline-block;\n padding: 2px 5px 1px 20px;\n margin: 2px; }\n#SITRBoard #BuildTab table tbody tr td.building.winegrower0:not(:empty) {\n background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAUCAYAAAB4d5a9AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAASAAAAEgARslrPgAABQRJREFUOMuV1MuOHFcBxvH/OXWqurqqu6vdM56LZ3wZC5w4G8OCBSAQCCkSEjs2bBBSFlGMxIKd90hIvACWeAUktjwCQjFJhBNMhtie8fSkZ3r6Xvc6dc5hwYaFjcj3AP/f7lO8YcX8BZ7qPFxMP//9p+MPeTb7J23jcyMZcf/GPRbFnLTc8M2b32V3/8EvTVs97m4dvbal3oQ4Y0E6yqJgPJ+xTgvAMtMNx7mmcRW+ryhNhjY1ranelHo9orMrVJiE6fLkrXU9Z1VO0brGU4Lalqz0DOEbnIpZBjOGXkrj8q+GGF2CtT/J8vEHJ/VTTKdE1gLnBNZYdFPTESFeENDQoJ1Gu+arIQAOZz3p235vSCeaUBYtrXaUmcE5h0g0XQFN5jAJtJr/H6mzKSAinIkDf+c0zPbfDuRzgm6FaR1VZslmDnEA/X5Ar7NF38Tf34v2F222+rNzduP3R/8bsbpEeP6Pi+X4D+cnZ+EXH51xpS11CBZBMQe77lBHIVVkSasLzk7/9rNef/jT/tbtx73B4W+yzXTWG+y8HtHVHNXph+V8/L3F+UX49Mkzzk5mrCtBGA8JE0FgHG3XIFSJ2mk4LRd8/I9P2D3o+/f51q9uCRcn/VuP/htSALZZAiK2unq3Xpz/oLw4f3/xfMrkyyV5VXM9HvLO3j7KF1hhSW3Gy3RMXhSEMZioJfVrxuavgjnvHToYJbceZel01uvvoNpq0W/q8kdllv8wnZ+/v766CrPTBek8w5eSuNNh1OshBMSqg5CS5TKnsgIuQOxCnChMBWmz5ovqL8K04j3hBMng8FG6uZypJlv9bjOb/OL5i9Po2dPPOT27gFbwnaO7PDg4YFmWSCkpm5rxZkleN8yKDYO3fAZJRKsrZGCoU0e2dqhww8v6Q6E8+Z7viYvR8P5vVXH16uHl30/47NNjpqsNurZEgU/aVCRxxG6SsCoK5nXDvyaXTLOMOFHc3tlChYa8AuEE0RZIKTCNI+/MuXRPxG69++uoGh4rXaaIquXta9e5k4xY1TWx73OZbfjo7BWDTkimNfM0RbcGTwqGOz7Jnseq0hhjUYCnBEKAaaCtHZldMTHHUccd7KvWWPKmBiEY9npsDQbgHKuy4HhxSVZVaGsZdEMOt0cYYQj2S9pgTZs34AALtgYZgghA55AWFavehEqsUFmRc3w55eJqxXaSsNfr4Xsem7phWZZsioLtfp+v7e1xmAzRXsM8uSTfrDDWISRY45BW4EmwgBeAtQ6DxmJQSsO1KOKlvuLldEpRlgSeR9223EgSpIDr/T5HW1sMOiHnm5qrVxXCaKItiW4N64VjuC/oh5JaO6x1oAVSd5BOobJXOZFQxN0O803KYZIw6vWojUGbluPZlHVecjKf0REeZ4slxD637t4gcHA5zsgmGVHcIg8EnudopcOrQ5LikG4zQk1WCybrDUXdUOmWQmv2g4BICBZ5ThxGSF8hQ8WqLImSLl8/usm9u4coKZisJnySPcepKZ7X0lUS3Vh8EXBNbhOLHurmN45IP3vOnue4di1Gh4JxmaK0wzhLMuryzt277OxsIX0fKSRR3C97w93HUgj6vd2Hnduj7lg8xbhzrKyRQhJ4IUr6CCFQRw++TRh1qPP1fw4SwXxZMXkxI4ljbt4bsXPrwA227/wxCKMngOfgS+EFf0IIBt3ux3eS7Z+7sXl3nBeY3hQhwPdCpJDg4N+FYbSjpEdluAAAAABJRU5ErkJggg==);\n text-shadow: 0px 1px 2px #FFF; }\n#SITRBoard #BuildTab table tbody tr td.building.stonemason0:not(:empty) {\n background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAUCAMAAABPqWaPAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAGBQTFRFAAAA8d/I6N/WzcS26NG27Nq68ezjv7Gotq2fyLqk1s3EqJqRraSWsaSW2sit0c2/pJaIrZ+Rn5GDqJqN49bE39rR7Ojaloh639bIxLqtsZ+R+vXxsaia39HEjX9xsaSaTMajHAAAAAF0Uk5TAEDm2GYAAAAJcEhZcwAAAEgAAABIAEbJaz4AAADqSURBVChTpdDRboMwDAVQcBoTEqgDrkMAk/7/XzZM2tpufdt99NGVZTfNf9OCudhPYBE6138g69GHYeyvf4AAKYYhTL/Mkgf0M08hcnijmxFJZolVIvevlUwisHKc47u0IpT9Skhb7cSntAAnGNxFtdpTEmTyhiTtnlXHsb+8islIaTfzKcrXH/EkCCbt3aLOOVX9llSPSfkA1BLU6aTuHNsWs5cE4gXwXnjbmL86FjA7t66GThnKzMxx2yrcAKXuHIPr/ClLpfqgxh6ShOKkyjG6nO6lLHwe2xz1J55inIYwL+EALqXMNcsD5M0SNKvkKqsAAAAASUVORK5CYII=);\n text-shadow: 0px 1px 2px #FFF; }\n#SITRBoard #BuildTab table tbody tr td.building.glassblowing0:not(:empty) {\n background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAUCAYAAAB4d5a9AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAASAAAAEgARslrPgAABJxJREFUOBG9wcuKZGcBwPH/dz3n1DlVXdXVPe3ETHomMQaSjYLEUYgv4CZP4VpGwQjZZOvChxDyFBJcBATNQjfiIgbNMEmc7uq6nfv5bjJCgwxMsvP3g/8DwTdw3RYQ8zg1b4cQTKMqTIrkTE4Z+2egttUdvo7ma4Rui9Sm7Jvtz7tm9+s2SH1QkozAWg1jWc7fTYmP+AaaF/DtBill2da7R9vD7v0ntbNHc8EkC3IZiJnUImXvrBYnH3ddPc1mc15E8wLj2CGFfLg97N77y5Wz2zTHFBmZkURheDJpoTr/y0Ttk+8/6XZPfGbzTxIcdXnG/9KuvTlxU/+DPkg7qgxFYiGGKa+qP17dHO0XjTePW4nMFGVISJmAQKsE/x5U2Q37D1y7Cy/Nzbhart+NKX3Ec7Sfuneaev/h08kUo52jCTgx+NLzGyPiaYjJxCiwUqGVJCZwISGFZDvBv652srm5kt9/sNb5ib4/jAPP04Pz+VXrsn8MpRG5RYrERmhzMbXvr0SDjgNSFCgh0BLGEEhSEBP0XcfjL27wfct07zTFRJsQPE8HNXurS40dMcgoUVJQY5icVrUuaBNEEiklIhGXIkSQDrabaw6HIzPpyYUXWRrfPFuflq69aU255paMQp4GlMiNpLAKKUAIGDHsYklnzojSMsXI6CISiUqCpm7Yba4JbsLmOcJkwo3tr/p2/0gIWU7NNbfkFCWNlygSF5Uh15KU+K+QQNkCYwuUtrgUiSnhXGCz3dLUNcUs5/LBJdXFA3pV2rE7vueG+mGYOm7JTPjrLA3ppm5IMbDMNTEmfIj4GBl8ososhVaYFOndwM1+R725QmnNnW/f4+TsLk6XRDsnRm9SnGwKjlvSCv+301x2wnV8frVDi0hhBD4mXEgMPoFULHPNMtcI5/BDQzXLeOXykrOLu3zZeD7bdAwBktQkNFFobslqNv/9+uTkt/fnKe0Oe77at5RWIgU4nxh9oO5HpFLkNsM7h02OV1/5Fm+9dsnd1YIgYNP1NF7Sy4UOMvtxWVala655Ro79oVnl+g+vLnV7nk082R459hMzq4gkfIhMIbDvHTElTnLNd++/zJuv3eflszmnpeW8LMi0YoySYzCia/ePur7/0Tj2PCONLRYIOV/Ol399YynB9zzd1xQ6oUWiGXq0jLTTQDNFLs9P+d7lXc4XM5QUOB+5t8z4zqpi8oLHTeTLLszGwE/L+bKcmg3ST/1PDofN7z7ftw8HNWc+K+nHkWPbU1lJZiTCGJQ1LErLS+uKKCW9S8gkaKeA1ZJ1Zeh85HpM1Mky9Yefjc3+h37qkM45u+/H/NMa/dlYYYqKRVVQT5HCaF6/s+SsynnjbMHr64Jn/rkdeFo7YoRMSVICAeQK+gBfdZpt54suqreL1T2ljbXjIjNTVTfZ3w+JrFqwynMW1rAqDOvS0IWc89wiBXx6M+JCZF1KaufZ947cS0QUrGaa4iA4tp62sKJP5heyH/4k89ni46xaf5iJhNtfMY0Dwzgx+QEjA1oLVoWhMBJSYpo8uRIYJRhcwihBTInBB6wSnGWK09JgZwsm7NxHsfoPqKt+g05SC1UAAAAASUVORK5CYII=);\n text-shadow: 0px 1px 2px #FFF; }\n#SITRBoard #BuildTab table tbody tr td.building.alchemist0:not(:empty) {\n background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAUCAMAAABPqWaPAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAGBQTFRFAAAA8d+/9d+W1rZ638Sa8dq29ei69dqD48h60baN9eOf+uzR+uio7NatupZs8d+f+uOR6NGRza1sv5pfrY1oyKRj7Naa//G6/+yftpFa//r1/+yopH9RrYhW2rpx7NGDIqezSAAAAAF0Uk5TAEDm2GYAAAAJcEhZcwAAAEgAAABIAEbJaz4AAAD4SURBVCiRpY/ZcsMwCEUdLQZL3iQZO8RC+v+/jJpMm2mat/IGZw4Xuu6fdVHafAS2BxzsJ9IrcGawf5kfQVllBvOGrPdKTQa1nt82Wr+svQ8xprTRr7Muu3L+uGLiVvPLutz8ovrjvCrizFG26Sf9tjt3nOsKJYkUnTfzrUzVja42gJozVcr5MW+vVKeqrg4JMQqXwvICheoJkUvFJETCTxDGE1N0KxLrClqYRJ7GeASKu6uFOCJUlsRfOX1Qrn1Yr7XExKkAlCwtx/chBB0jroCRmFNbB5R57pYQzDCYHdaHwk0GQMlzZ+00Tda61upE0exmV4CUtztm+xM5HuXJowAAAABJRU5ErkJggg==);\n text-shadow: 0px 1px 2px #FFF; }\n#SITRBoard #BuildTab table tbody tr td.building.palace0:not(:empty) {\n background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAASAAAAEgARslrPgAAA2BJREFUOBEFwU1rXVUUgOF3rb3P1725yU3TWJWohEJxUJ1aOlBQiujQiQNnIo6c+gsExwqCv8BB/0HFoQNxoKK2tIJtKNUYaz5u7kfuOWefvZbPw4M7n/rRwY9/zufnbw/u4u5yPjt55+jJL48e3r3tR38/OJ7N5u9fXKzicrHg8PHPzM/Pbx49+f23+z994wd//JDPTo8/12ZjjuV/r1ruvhra7mbq2tdy7r/ou9P9jY0Gd3bykL4U93erKk6fffH6xOz8s747fGU6XrPVLDVo+kQWhx+6FLcg3nDr7VhD9lDqZfessaxxxljGh3Z1lrI+kEJ/jfHoA8nHm1EL8ICWLyEHd95zqZ/HR9dwNmmaRF2tqEYVcWMPimdoVwOr0wUXXcBCJPhDtptjoOFiLkx2XiW2s4RUh3jbos0lRhFUM+Rt3LbAJoRYE8uBsHhEoSvq8pjg0KVMu4QYz4giEBgIPiNKopKGGDYgNECJSCQUI4oyoN0B2ClVdKJMGcTAhdSuiQioOJGBJhplFQgFuGTAgICIEDwj7SmpOyYVNbFsEHrcA9kyigACIGgo0FihwRDJOAEn4gQEJ4ihPmBpwIeMqCFqSFAigAiIAAhgCAkk41IAEQccQzAcMHfAUUkEBRHQdQd5ANxx67HUkrPiFgFFUBRDLGPmZAN3MAfLjpARG4iHJ7CbYVOcInV4rsm2jdAQyIgouIKDO5hBGpzVGlJf0vZCEyGC899caLOjVSZURgiBUAZ8GNAwYK503cC6c1Zr6DGiDEgTaXulrJW4u1Ox7hLuznIlSOWU0qG0xGGFlHOMmvVizcnS6NewWQujQiE4rSgSIlruvMxkc8JkLNS1EgslFIbIgHuHWwIMCU4ZYdzAqFY8G4uTGX2XCGVF1MuvM+gYWd4je09OiZg6irKlKnukMnJOWDCq6LQ9LBaZfrai65Vm+hyxHhF3965/N2/Gb3G+pXn9F4MM5LZFfU4rJdovsWTkQdDRCKxlnXaRsMX0yh7TK/uMp1eQ+XK1N3SLj3SYXfXh4qkW+aZz94bqE0S3Qd4AuwQ+x/P35PyYlG89tbR9Oyj36o2tF8qqOhJ3BxDA2y69ebE8/Xpxdv/aOM4QE8ymuAfAwM/I3tGynyY7+99uTLY+tpz/GY8b/geGd+pmTCUDLQAAAABJRU5ErkJggg==);\n text-shadow: 0px 1px 2px #FFF; }\n#SITRBoard #ArmyTab table colgroup col:nth-child(even) {\n border-left: none; }\n#SITRBoard #SettingsTab .options, #SITRBoard #HelpTab .options {\n float: left;\n padding: 10px; }\n#SITRBoard #SettingsTab .options span.category, #SITRBoard #HelpTab .options span.category {\n margin-left: -3px;\n font-weight: 700; }\n#SITRBoard #SettingsTab .options span.category:not(:first-child), #SITRBoard #HelpTab .options span.category:not(:first-child) {\n margin-top: 5px; }\n#SITRBoard #SettingsTab .options span:not(.clickable), #SITRBoard #HelpTab .options span:not(.clickable) {\n display: block; }\n#SITRBoard #SettingsTab .options span label, #SITRBoard #HelpTab .options span label {\n vertical-align: top;\n padding-left: 5px; }\n#SITRBoard #SettingsTab .buttons, #SITRBoard #HelpTab .buttons {\n clear: left;\n padding: 3px; }\n#SITRBoard #SettingsTab .buttons button, #SITRBoard #HelpTab .buttons button {\n margin-right: 5px; }\n\n.toast {\n display: none;\n position: fixed;\n z-index: 99999;\n width: 100%;\n text-align: center;\n bottom: 5em; }\n\n.toast .message {\n display: inline-block;\n color: #4C3000;\n padding: 5px;\n border-radius: 5px;\n box-shadow: 3px 0px 15px 0 #542C0F;\n -webkit-box-shadow: 3px 0px 15px 0 #542C0F;\n font-family: Arial, Helvetica, sans-serif;\n font-size: 11px;\n background: #faf3d7;\n background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #faf3d7), color-stop(1, #e1b06d)); }\n\ndiv.prog:after {\n -webkit-animation: move 2s linear infinite;\n -moz-animation: move 2s linear infinite; }\n\n.prog {\n display: block;\n width: 100%;\n height: 100%;\n background: #fcf938 -moz-linear-gradient(center bottom, #fcf938 37%, #fcf938 69%);\n position: relative;\n overflow: hidden; }\n.prog:after {\n content: "";\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n right: 0;\n background: -moz-linear-gradient(-45deg, rgba(10, 10, 10, 0.6) 25%, transparent 25%, transparent 50%, rgba(10, 10, 10, 0.6) 50%, rgba(10, 10, 10, 0.6) 75%, transparent 75%, transparent);\n z-index: 1;\n -webkit-background-size: 50px 50px;\n -moz-background-size: 50px 50px;\n background-size: 50px 50px;\n -webkit-animation: move 5s linear infinite;\n -moz-animation: move 5s linear infinite;\n overflow: hidden; }\n\n.animate > .prog:after {\n display: none; }\n\n@-webkit-keyframes move {\n 0% {\n background-position: 0 0; }\n\n 100% {\n background-position: 50px 50px; } }\n\n@-moz-keyframes move {\n 0% {\n background-position: 0 0; }\n\n 100% {\n background-position: 50px 50px; } }\n');
  3786.  
  3787. //jQuery UI CSS
  3788. GM_addStyle("/*!\n* jQuery UI CSS Framework 1.8.21\n*\n* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n* Dual licensed under the MIT or GPL Version 2 licenses.\n* http://jquery.org/license\n*\n* http://docs.jquery.com/UI/Theming/API\n*/\n\n/* Layout helpers\n----------------------------------*/\n.ui-helper-hidden {\n display: none;\n}\n\n.ui-helper-hidden-accessible {\n position: absolute !important;\n clip: rect(1px, 1px, 1px, 1px);\n clip: rect(1px, 1px, 1px, 1px);\n}\n\n.ui-helper-reset {\n margin: 0;\n padding: 0;\n border: 0;\n outline: 0;\n line-height: 1.3;\n text-decoration: none;\n font-size: 100%;\n list-style: none;\n}\n\n.ui-helper-clearfix:before, .ui-helper-clearfix:after {\n content: \"\";\n display: table;\n}\n\n.ui-helper-clearfix:after {\n clear: both;\n}\n\n.ui-helper-clearfix {\n zoom: 1;\n}\n\n.ui-helper-zfix {\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n position: absolute;\n opacity: 0;\n filter: Alpha(Opacity = 0);\n}\n\n/* Interaction Cues\n----------------------------------*/\n.ui-state-disabled {\n cursor: default !important;\n}\n\n/* Icons\n----------------------------------*/\n\n/* states and images */\n.ui-icon {\n display: block;\n text-indent: -99999px;\n overflow: hidden;\n background-repeat: no-repeat;\n}\n\n/* Misc visuals\n----------------------------------*/\n\n/* Overlays */\n.ui-widget-overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n}\n\n/*!\n* jQuery UI CSS Framework 1.8.21\n*\n* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n* Dual licensed under the MIT or GPL Version 2 licenses.\n* http://jquery.org/license\n*\n* http://docs.jquery.com/UI/Theming/API\n*\n* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=bold&fsDefault=1em&cornerRadius=4px&bgColorHeader=F8E7B3&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=ffffff&fcHeader=542c0f&iconColorHeader=542C0F&bgColorContent=f6ebba&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=eccf8e&fcContent=542c0f&iconColorContent=542c0f&bgColorDefault=eccf8e&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=eccf8e&fcDefault=542c0f&iconColorDefault=542c0f&bgColorHover=f6ebba&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=eccf8e&fcHover=542c0f&iconColorHover=542c0f&bgColorActive=f6ebba&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=eccf8e&fcActive=542c0f&iconColorActive=542c0f&bgColorHighlight=f6ebba&bgTextureHighlight=07_diagonals_medium.png&bgImgOpacityHighlight=100&borderColorHighlight=eccf8e&fcHighlight=542c0f&iconColorHighlight=542c0f&bgColorError=f6ebba&bgTextureError=05_inset_soft.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=07_diagonals_medium.png&bgImgOpacityOverlay=75&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px\n*/\n\n/* Component containers\n----------------------------------*/\n.ui-widget {\n font-family: Arial, Helvetica, sans-serif;\n font-size: 1em;\n}\n\n.ui-widget .ui-widget {\n font-size: 1em;\n}\n\n.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button {\n font-family: Arial, Helvetica, sans-serif;\n font-size: 1em;\n}\n\n.ui-widget-content {\n border: 1px solid #eccf8e;\n background: #f6ebba url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAABkCAYAAAD0ZHJ6AAAAfUlEQVRoge3OMQGAIAAAQaR/Iiq5u0oEhht0+Etw13Ovd/zY/DpwUlAVVAVVQVVQFVQFVUFVUBVUBVVBVVAVVAVVQVVQFVQFVUFVUBVUBVVBVVAVVAVVQVVQFVQFVUFVUBVUBVVBVVAVVAVVQVVQFVQFVUFVUBVUBVVBVVBtVtsEYluRKCAAAAAASUVORK5CYII=\") 50% 50% repeat-x;\n color: #542c0f;\n}\n\n.ui-widget-content a {\n color: #542c0f;\n}\n\n.ui-widget-header {\n border: 1px solid #ffffff;\n background: #f8e7b3 url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAYAAAEwK2r2AAAAY0lEQVQYlaWPMQ6DQAwER/v/7+UhQTRH7N00QEESiUAzki17vOb1fEQAR8QDpSaUmhHkYwSAb4LEKD2vAryc3/2JpFC8IDzWfHgg0qcEd47/haT3VEZxbWUKQW89GhFffeEi3kGvSQXcQU8oAAAAAElFTkSuQmCC\") 50% 50% repeat-x;\n color: #542c0f;\n font-weight: bold;\n}\n\n.ui-widget-header a {\n color: #542c0f;\n}\n\n/* Interaction states\n----------------------------------*/\n.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {\n border: 1px solid #eccf8e;\n background: #eccf8e url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAGQCAYAAABvWArbAAAASklEQVQ4je3Puw2EABAD0fGw9F8KFSFqgJTgCPhEFHBCmzxN4sCs8/QToGmaz7JvC5JgMiAnhbEwjoiFPpXUXda1SPyHM03TvHEAd0QJtjgD5PAAAAAASUVORK5CYII=\") 50% 50% repeat-x;\n font-weight: bold;\n color: #542c0f;\n}\n\n.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited {\n color: #542c0f;\n text-decoration: none;\n}\n\n.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus {\n border: 1px solid #eccf8e;\n background: #f6ebba url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAGQCAYAAABvWArbAAAAR0lEQVQ4je3PMQrAIABD0Z/o/Y/Wk3RwLBSqg0KXHkBKlkeGv4SrHd0AIYTf8twnBmEkDF5IBTMxlupaM1HB0ht7hzMhhC8GEiwJ5YKag9EAAAAASUVORK5CYII=\") 50% 50% repeat-x;\n font-weight: bold;\n color: #542c0f;\n}\n\n.ui-state-hover a, .ui-state-hover a:hover {\n color: #542c0f;\n text-decoration: none;\n}\n\n.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active {\n border: 1px solid #eccf8e;\n background: #f6ebba url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAGQCAYAAABvWArbAAAARklEQVQ4je3PsQnAMBBD0S9l/8kyTFIaDDkXBkMgA5ig5iEdXCHafZYBQgi/5ekXrlmFpQNLxmDMTOv2rrU+kHYYE0L4YgB9ewvfYTVHjwAAAABJRU5ErkJggg==\") 50% 50% repeat-x;\n font-weight: bold;\n color: #542c0f;\n}\n\n.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited {\n color: #542c0f;\n text-decoration: none;\n}\n\n.ui-widget :active {\n outline: none;\n}\n\n/* Interaction Cues\n----------------------------------*/\n.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {\n border: 1px solid #eccf8e;\n background: #f6ebba url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAjElEQVRYhe2UOwqAMBAFx2DlMbz/kSS3MIUIWij4aZ/gK952YZohu0y3zNPGOWur3Kcfxsf7D16c5YBD0FUOoDjLAdeKHeXWVi9BRzk4f9BVDqA4y8HrBt3k0sEveDqo8nRQ5emgytNBlaeDKk8HVZ4OqjwdVHk6qPJ0UOXpoMrTQZWngypPB1Vu38EdG7NcOPXFHAMAAAAASUVORK5CYII=\") 50% 50% repeat;\n color: #542c0f;\n}\n\n.ui-state-highlight a, .ui-widget-content .ui-state-highlight a, .ui-widget-header .ui-state-highlight a {\n color: #542c0f;\n}\n\n.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {\n border: 1px solid #cd0a0a;\n background: #f6ebba url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAYAAABHLFpgAAAASElEQVQYld2PMQ6DUBTDbP/7X4grde/6GACpjN0QS+QkyhC+n20CeI3MQChJJ4GEka7LEtkiRsJF2llw0G02SP5k0oxPOP2P7E3MCpW4kdm7AAAAAElFTkSuQmCC\") 50% bottom repeat-x;\n color: #cd0a0a;\n}\n\n.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a {\n color: #cd0a0a;\n}\n\n.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text {\n color: #cd0a0a;\n}\n\n.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary {\n font-weight: bold;\n}\n\n.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary {\n opacity: .7;\n filter: Alpha(Opacity = 70);\n font-weight: normal;\n}\n\n.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled {\n opacity: .35;\n filter: Alpha(Opacity = 35);\n background-image: none;\n}\n\n/* Icons\n----------------------------------*/\n\n/* states and images */\n.ui-icon {\n width: 16px;\n height: 16px;\n}\n\n.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {\n background-image: url(\"data:image/png;base64,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\");\n}\n\n.ui-icon, .ui-widget-content .ui-icon, .ui-widget-header .ui-icon, .ui-state-default .ui-icon, .ui-state-hover .ui-icon, .ui-state-focus .ui-icon, .ui-state-active .ui-icon, .ui-state-highlight .ui-icon {\n background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAADwCAMAAAGvTnpvAAAA7VBMVEVULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxULgxwjo40AAAATnRSTlMAGBAyBAhQv4OZLiJUcEBmYBoSzQwgPBZCSEoeWiYwUiyFNIeBw2rJz8c4RBy9uXyrtaWNqa2zKP2fJO8KBgKPo2KVoa9s351GPm5+kWho0kj9AAATX0lEQVR4nO1dC2PbthEGyUpaqJii/JgbZ3bTLNmyJns/Oi1bM7vp0q7r/f+fM+JxwOEAkNTTSoxPlqHD83AE7gAQBIUYBHSfQv0XnbsJgH02A3g5ibVzDFNtlkPI1VjIuOUa8eMclOLS1uRSPBETURnOrkbmID9T9fuPyu+cSGYYKya5efeddN9TRS1H8eD4kDjrPutBpptt2apkiqX57A4gfloj7ua9AXMQ3dWvNs8n7NCwZk6bqYSg1CgNsaCBHDAluMQjcihEWBNYSxamUYNMs15KmwMUKhm0S5UBwMQFjcqxelSYskHBtLC26X7/eWQtVB1MaWXzF1OrUyhLgOrFiBwalDwg6+tigfzbnNbM40UlTrrO3clTftcuX7jyY9gkv81RVWI9K0OxNa8Hruw+EFctu6xaqDhCGkjQ2hyMitiXKyR+7xSqx6u6AitlpI3wrBj5OSo5xv8ZShoq5VZE+p/hb/OVzuPHyHGXQLoug9b4af/OzArAqtlvq8PidqZSflOYigVIpTZ33192wQ1jHVXLgjWWeZdAfhn3UteqH43NI9EGSjns7CJ//g8h6o6++UrLBTrOZJUkhy4NxDNAblZld53kJZl34z4jE5cB0HbA5RHnzg9Txud28wwG4aS1pwzKH7t/IyxlEvW2XVQLcf0vyeCWfL9j39vk95iA1alinhtmcHDr34tiSDECRgCXwFMgynMfrB0PlAxMhdUoPyKDo7qq2yNZHa+Li9BQoynz/I9DNkNcFCQSVi2aQbTOJA7S1tIXYpwM9t+PgBYzwFI0mNdt9JjxuGBHXJuwuJO+fq8KYzpDLtDll1XoYZ6k53P9dUNdNzwQZTcsvLw0Cafa0snfyq/WGVUVDo/VxBxXF5ynLZn6zUO/FvTIdjeiw3VUeyUqv7Q5+dIiz+W/VoTs03r+4U/ERpyHVbkIFAU44dGMKQBZfrwrGeAl4litNO9TVGFXRN1TDlfTyGVqdQaVEV7T0ZNJGO/NTQ9nL18aDk29b2Ui2SaqfhltIIMn4gpz+k+TiNNXkjf0LYWzf+DXO4UzHuF49WYS9pIIN3mjcoga1CNDuZ3kKzlja00XXS71OHFZjBhkI1K98WCQ/QC/r9n3qudrYVVea6aE9iP8L1A/KnWuJMZ+jwiyz+P3SFkcguW26os1MoON1p+35uAIgB3fXnzm2hscgvkD0PBi23t8YcEsP2u+gEUvdsXAg4VrA0y2zD/ZBgCjbz07ZNd4bBvYHQMPFcBFznsTv/hBOj9hkE0yvyRHcYZCK5VoEwGHQwU+dJBlX08BOMGx8MBk+I2oMHdQbLZFkGDADfVBQcmCx8Nb6S6fwJqRehFktWEAVsSA0yNP5DQm8wcW6tNr9D/T6PzGVgS2gP3iCoyPB/L4YF2A2ZICUKoZI06GSjdZYhdlxzeOLANIWxfoGkaofzK2BDRlWaq76VMAuRDbiXyhQiYTtV1L7hBS64vLpRJ/xbYMQRcPVPRT4802P5ruaHvrAv3BtDmzxwz3IsFcru92uL4GysByOVV7H4Rx7Xaqax2xvqiNEQId74svvjAcglfgwis/o+vnFdpxsCJHV8uomprlYHfNpPvrV79B4+G75+dG5i3NEGBh0+urAGWrXZ1uItAYmWJNQl28cCs1pd6/AX+c/Q0znEddU8OOLjEDWWF4qcsp8d7DgweI1Vv85bs8or6kK+g+8scLc22/Ed/oVI3WF9iGKrNzybSd8sQsS9u2sFyqiPXbaWpgH2Xg3x0Dclm+whsRABfKOXlh2tCpCqhMo3wGz54pBkxbsAxUN0ejCKbq/xXAt/dS/BPA9VC+EFC6jiTkrS8w3Raj+Sp2U/vcdFdGprxDRcPbAOa7LwYyOtEZlWh08EyUjdA/GtU4Gjs+bDxRN0bi6HbezUEZQGzNwIMHiB+NDMugG1UD7o4YwLne9MIbbEYGKNT9dIA2gLs/ALzrc1PphlwOAO/BC/n7Vk/DuL+lE67wdleAuQEH8sEik0/U0KMNuDMF3XWkvO3+wdDEFZQm6Vh6pAX47qfXeHYGMwcMXHc/wHc/PQYyAslWXNUPjNf3xEAlocNxqJjbQEYcW6sHO6bEH/6+VSgKf75S2AReOLiEa5Y/dEuF3/yKd0ootu+mvgQCzYt04TNUmPsNG0tga4ze+ZSRkYK3DiJCPYDdAb2ZHiiA78JZt/yge6XcIk67fLbVA1jASD1QILmlBDIy9o7Bxsn1APMeG5/b6SB9cHc9sO9sApTgPNXfXbJUuC2AxWPjjUiOzI3Hc8UmphFJCWQ8eAwehjEYbs2338j4cD+Vn4vgNfOwURsvXhxPDzwDay39+UVkOhCsiHrhwPovDyfxPIXC0xVJPeBqWlCPgvVzJ0FWgPEtyGZUxuCe9MB9zUcydgZ7BdksfFhBGKTM8tg2BkGHTlnJuEKx/d56r9m6gRXF7+ByBiJW11NAm8AoCKvj9HyfP7SfkkAwkjq0nc/jio8frDsFw+P0cYU7uvrh4NWz53avCrHwyOAuOAhvZiV6HVMIUk/uyA6GEwJGl0bReIzu8CZc0AY44o0gd/9PBvIcKObhX91HzAPMHrUK2L0tqD/T/oAbEAVx56B3qorHj9VZBNJHBTSN2lQrThpbkD4EC/RmWWQAhN78BuA2yanYE9x9e1pp9+yMdWug0QXeRJ+b8krTnxr80fGjU1xeegxMBSx1Rrr8EnS8y0t5aIIQ9RN9auPZZHJmJOXNM9w8QTEwh8efewwUGHE+n+uI1zpDZKCaLpfGVcGV2b173UGlr29qUk6EgQml57CQG4QcA5TRn1EJGgbsFlOMv4AFnbEALxBdvgfNVlSXn3EMAF/XRwaVyuM5wHNFJFp3uM8A82HXGs7NjxbbRlWKSCMSv/rVCWUgCEfU5jH8Whh3ot1WNz6WbmHTT1vbzSvKgBXBye+/NByKSEYSqpteGwauDQPXhoGW9PvGT69OZr2wvcNUcHph+gXwGgvGgFZATy8vvxby0FPtz11Tf93Pjat3eL9UbtvagQ+qWkfjIwhO/iLZBsC/zWFdc4G1itWc6Lb2WDcKy2DG/aMO1vH6R3t27PjCtIXpP75Wrum0V1/Bjc5GWc2paSvKVSeR8940C1az4gykFNA34hvQJXkPVGDrh6py4wHtoY1Y+WapTwOfBt3Ob+WkQI9BG28+V/sLG+N/bgYypUt/Kt0XZsemTffmjcloOqs3kACgNcVN+ivQjx24eYRO9uwZPMOKUAlMb27YyT4DDJBoOh/HmXbeGkl+hTnp55W6SyA1ZroNZJjnG8S3AGPO9t89njijpTk4Mw+ruUs0avB2BrDuEf+mHHnAE2mlfBlAdjBjThWFg8z2++/ZAw+btanGdivMqTEVhlea0uW7ckrbzTw9UZ2dbbTjWz3h0RgG7igDlkEzTBiQwKbdStXgTB7hhRlYCQiPzMhIAxvLpsnBNjrVrRqhH3ppSv1jpg8nlP9mJoGJj+lM2910mZzNBwDMdn0xw+410wzMfIXDxiWb27aNJeAy0PHvb0PAlm0g497xX3iqXIDt3mO0KVb/A2FGszM8bg9GfHcGm2EN+KCVHh8sl4V+mL7Qy3MAS/NwPezy9UJi1op2pjkxi7ZuJWPR4+4O7+H9TvPLWBs4H+DuO4Af+txUuiGXQ40JrxLu6wE3la7HjTCgmz3OC9TDdhDxd0/Tob+I+/PvTz9h/JuYAjFzAueCHHjHMjIF8PhheogycCPiT9vjfEBVVLq3nced8f9g/FPuHU3PXAG+Czdm3sGA8wHufjfgptINuRkZIfD+YOCyWe/eGlFQEDIg/P1B+2PgviWQkREg3dYO9FRZwACWe6in2gwD+NBtV26B7kElgAwcvPxEGyiKw3GQ8QBRHPv+9K35692kXajXyBZe5INKRO5gouVBMPIoIHi4koV6Ebge4cnDAoLIQYl7hCyKn8naK4CYgHorGAqgh4HDC2AE9tsFeBM8eBfIyMjI6MfeleD9qjw+DnBbmxGRCDy6byf9ChVhdn1mtVBLnIeTCUB05MOieGZqxDigEH4CP3xo2HBQAYzAJ94FMjIyHjq2XnbfMoNgdtx7J2CD2wT9CfANgl4ZfTlAkCNwisfvzz3yLCewQEgEmgxDflgCSAXGyh8Rg1UwfMtiT+KIgHwGY8n7r9BwCT2BkfRrY9sM9pu+dwUqIyPjoaPgkzfRf0s+EhCJ3G/HvdAEAyRc0PnYCIXGz0blRotPziJ2mZcCvQyEwwaP/3CUMzDskBGARqd6HDgHTIAmMnAPR4c+veMwVn5Yg1HBwQKDT7L4rH6CryEERfAKFLQFsJsMMHQbJNrIe4oPCgiCw/wYf/wKRhIwjnsFEEbO44CMjI8ae+3BgZliWiksXKYoPLsSYIDjwDDz6W+wjN4XviWMlUrewFZBPff/I0rWn9+GDPeZBUwLNACCiLuUAJ5sTwsBL9yrYsSqhwz1iShYgIm0ACaAsIXs3K75A5lgnZ7dGBlYxx9a8hkad/QPmzIyMo4O4bvWPipEZxa+4imDCRuf//HnMIcV3bHcEYXYKrJvdUooPbPk2U3pll4OIDhJBVYgfSytZoQAgvj+AoU+rSshAL4+gZU/mgYghrpAtL2T+GX8akLkl0Q48v4EcE/PYWdkfBxQx1SucfLOZ/Ik0c/2x48POGmaKdFz9jAsF0N+F1wLOlXWVpo2h+dVuApcxelg8jc34eZgVjGp5QOE9cRjQARmhE4vg8mqx79mnpeIHlDKg1ZdKmiaotTADLrr4Zd3LpESAOiXooN7N7ppAUjrdX3C8blKbjOcwOnF/OdABSCPdmX15fUP7BSxYr4AZPU/d+FQ+hKFgnnIV+EVy4KsAMHFxUW6BcBy2bWiqXlJvCq4Un9WADJ+RQTwVKZ++hQ9TuXpf7U4ZdUhCSp76CxG8C2576EE8As6Llm0j8EdZxMIICjvmQKT+MReIS6AaqmAHAY0yF42Be+K1LXtAjWWbw8YCRj6Qn18fvpbAA3XXa4RO0NVtQpbvFLaKYCR0WGr0VQ+8zfjoeHLL3uDS3kmqR3Nz6TNe1FPnc551CmRxSOrw6K9r3L+z40Sfo7pYSHBJle+Havreg1az9Tsob2NVOSl7delPHZoQdcnXgK89NmVZyK3F5iZttOWv4LxB3pUQNYDvnr6+s3VUzJaqrqhEzl9VAsgVWH4Lfyu+8xIBaXmrxlNzU43KpqQ8NZn0NgxO27xy/sSSdIKZnDSQmslBLIFuPoFAtAC9wTwi3n3IdWnI11ACVi6BDXYQvoP8Jfu81e3QOJfYUVXjCbh6up1QMPRqKKcZUO7Turntbc2sCEAZPYfWbvSR0Yn7Q6wgf5zw4DrAnJBia8vWCbkxWbZ9dOCn1gddKmSVl+8/vtCiMXfXxuylVe/b/pe94QdLdY5DbRt85HfGfeOKR2MSy0G133R97uMWMNsOn0LtO/3bxsbQtvlVTtNBfI48BXXwxdOKf5T4l9OC6+mXQatm67FzHJkyZXO76nhli9OkYev2/J0gDOrnQ1fyUK9Cvu1Z1rWAwThej7nBLpS9MrSpR9fu3Ob/F0XNAMiwIkCEYBvReTAjUSQ50F3VboQVADdOIxIqr65kXbV0m8lc25cEkiceSTItAD+rWgci5V64OU0cb1SuPCTO3l1NTo/P/cEQASnVicunnZ/bIFjlWwBNzfd7Jxez9rnV+y+C7yUo1Fn97nNWi0WfyaFNd1f6UQAnoM/5+gxRfmbkakSiEKiBcBUAqLnDN4TTu/uTgnZnshxSokvAgt7oF6B2WL9ISPDx3sg58x+h03uu3vk6LB4Ly0HSuCD7m7y/wcbgynBmFFsnGprPSUf8eA0qBcWuNc29BjdfaC7/tJ0vvcK93lYsJONu+gzS8iKN0S3Bzqrq23Z0vWN77t/33sRzrwUhxWAqzAtvJ8HMttUVfdM29YCUMSG7/FYH0Ag6deOfE0jsUSE8KsvdtAFehYfDoEf5FgU3v1wnzwc0SAlI+PTB8zY7MRfJd0DHj3y6cYvrTnkKEAYQ0CF4AnAhFlNr7hrZsAj2C0UcsxAw0Obyq1kOAiQ5GFHAocUQKrGjDygAA7cBfhA6d67QEbGg8eDfj9s2c1s4ceG3C+sm3dskVQC9dLCTJUWG9LHhlK+bvHHRryit5NXF2Lm30Eli6qT80n3Z9ep4RzO6cK9pMGnJ/IzOVLNXur3TVIB6Fax8tahiQC+1sBV2XXpo0MN8OrFK9rm1TCgacg9p8hZUxkZGZ8I+H2AIfoW6dvN6HXL25YeAr8P8AEskFYvQrs19J2Kr8LvLA2cFsnwDy78Q7J8Ab3hcvmUhfu0zsLd1+gDkLu2CVpeO/vSMHAFJuOTaCLiBvHBjz/Ij8BvgpY3fm9swmEBcAYsbLlyX1Wa4WHaz89GSAgIXKy0gHpo/Y67sQLg9wGG6CtHX21Cr1vetvQI8PsAQ/TVt5L+9mpTet3ytqUzMjIGYHTG3uijh5yr0+k6+PvyhJ7PexUU/QIQ9LnA40cWwEPvAhkZGftA/3tFjgqFGDocrRpc0+XV/ahenOIJAAr8ED8qADvbojmAL4BCvUFvX/zuHNsKQMcXlP6IW0AM/V0gUf2PtQVsC3UAp/lmHDv+D/qKcxyg6AblAAAAAElFTkSuQmCC\");\n}\n\n/* positioning */\n.ui-icon-carat-1-n {\n background-position: 0 0;\n}\n\n.ui-icon-carat-1-ne {\n background-position: -16px 0;\n}\n\n.ui-icon-carat-1-e {\n background-position: -32px 0;\n}\n\n.ui-icon-carat-1-se {\n background-position: -48px 0;\n}\n\n.ui-icon-carat-1-s {\n background-position: -64px 0;\n}\n\n.ui-icon-carat-1-sw {\n background-position: -80px 0;\n}\n\n.ui-icon-carat-1-w {\n background-position: -96px 0;\n}\n\n.ui-icon-carat-1-nw {\n background-position: -112px 0;\n}\n\n.ui-icon-carat-2-n-s {\n background-position: -128px 0;\n}\n\n.ui-icon-carat-2-e-w {\n background-position: -144px 0;\n}\n\n.ui-icon-triangle-1-n {\n background-position: 0 -16px;\n}\n\n.ui-icon-triangle-1-ne {\n background-position: -16px -16px;\n}\n\n.ui-icon-triangle-1-e {\n background-position: -32px -16px;\n}\n\n.ui-icon-triangle-1-se {\n background-position: -48px -16px;\n}\n\n.ui-icon-triangle-1-s {\n background-position: -64px -16px;\n}\n\n.ui-icon-triangle-1-sw {\n background-position: -80px -16px;\n}\n\n.ui-icon-triangle-1-w {\n background-position: -96px -16px;\n}\n\n.ui-icon-triangle-1-nw {\n background-position: -112px -16px;\n}\n\n.ui-icon-triangle-2-n-s {\n background-position: -128px -16px;\n}\n\n.ui-icon-triangle-2-e-w {\n background-position: -144px -16px;\n}\n\n.ui-icon-arrow-1-n {\n background-position: 0 -32px;\n}\n\n.ui-icon-arrow-1-ne {\n background-position: -16px -32px;\n}\n\n.ui-icon-arrow-1-e {\n background-position: -32px -32px;\n}\n\n.ui-icon-arrow-1-se {\n background-position: -48px -32px;\n}\n\n.ui-icon-arrow-1-s {\n background-position: -64px -32px;\n}\n\n.ui-icon-arrow-1-sw {\n background-position: -80px -32px;\n}\n\n.ui-icon-arrow-1-w {\n background-position: -96px -32px;\n}\n\n.ui-icon-arrow-1-nw {\n background-position: -112px -32px;\n}\n\n.ui-icon-arrow-2-n-s {\n background-position: -128px -32px;\n}\n\n.ui-icon-arrow-2-ne-sw {\n background-position: -144px -32px;\n}\n\n.ui-icon-arrow-2-e-w {\n background-position: -160px -32px;\n}\n\n.ui-icon-arrow-2-se-nw {\n background-position: -176px -32px;\n}\n\n.ui-icon-arrowstop-1-n {\n background-position: -192px -32px;\n}\n\n.ui-icon-arrowstop-1-e {\n background-position: -208px -32px;\n}\n\n.ui-icon-arrowstop-1-s {\n background-position: -224px -32px;\n}\n\n.ui-icon-arrowstop-1-w {\n background-position: -240px -32px;\n}\n\n.ui-icon-arrowthick-1-n {\n background-position: 0 -48px;\n}\n\n.ui-icon-arrowthick-1-ne {\n background-position: -16px -48px;\n}\n\n.ui-icon-arrowthick-1-e {\n background-position: -32px -48px;\n}\n\n.ui-icon-arrowthick-1-se {\n background-position: -48px -48px;\n}\n\n.ui-icon-arrowthick-1-s {\n background-position: -64px -48px;\n}\n\n.ui-icon-arrowthick-1-sw {\n background-position: -80px -48px;\n}\n\n.ui-icon-arrowthick-1-w {\n background-position: -96px -48px;\n}\n\n.ui-icon-arrowthick-1-nw {\n background-position: -112px -48px;\n}\n\n.ui-icon-arrowthick-2-n-s {\n background-position: -128px -48px;\n}\n\n.ui-icon-arrowthick-2-ne-sw {\n background-position: -144px -48px;\n}\n\n.ui-icon-arrowthick-2-e-w {\n background-position: -160px -48px;\n}\n\n.ui-icon-arrowthick-2-se-nw {\n background-position: -176px -48px;\n}\n\n.ui-icon-arrowthickstop-1-n {\n background-position: -192px -48px;\n}\n\n.ui-icon-arrowthickstop-1-e {\n background-position: -208px -48px;\n}\n\n.ui-icon-arrowthickstop-1-s {\n background-position: -224px -48px;\n}\n\n.ui-icon-arrowthickstop-1-w {\n background-position: -240px -48px;\n}\n\n.ui-icon-arrowreturnthick-1-w {\n background-position: 0 -64px;\n}\n\n.ui-icon-arrowreturnthick-1-n {\n background-position: -16px -64px;\n}\n\n.ui-icon-arrowreturnthick-1-e {\n background-position: -32px -64px;\n}\n\n.ui-icon-arrowreturnthick-1-s {\n background-position: -48px -64px;\n}\n\n.ui-icon-arrowreturn-1-w {\n background-position: -64px -64px;\n}\n\n.ui-icon-arrowreturn-1-n {\n background-position: -80px -64px;\n}\n\n.ui-icon-arrowreturn-1-e {\n background-position: -96px -64px;\n}\n\n.ui-icon-arrowreturn-1-s {\n background-position: -112px -64px;\n}\n\n.ui-icon-arrowrefresh-1-w {\n background-position: -128px -64px;\n}\n\n.ui-icon-arrowrefresh-1-n {\n background-position: -144px -64px;\n}\n\n.ui-icon-arrowrefresh-1-e {\n background-position: -160px -64px;\n}\n\n.ui-icon-arrowrefresh-1-s {\n background-position: -176px -64px;\n}\n\n.ui-icon-arrow-4 {\n background-position: 0 -80px;\n}\n\n.ui-icon-arrow-4-diag {\n background-position: -16px -80px;\n}\n\n.ui-icon-extlink {\n background-position: -32px -80px;\n}\n\n.ui-icon-newwin {\n background-position: -48px -80px;\n}\n\n.ui-icon-refresh {\n background-position: -64px -80px;\n}\n\n.ui-icon-shuffle {\n background-position: -80px -80px;\n}\n\n.ui-icon-transfer-e-w {\n background-position: -96px -80px;\n}\n\n.ui-icon-transferthick-e-w {\n background-position: -112px -80px;\n}\n\n.ui-icon-folder-collapsed {\n background-position: 0 -96px;\n}\n\n.ui-icon-folder-open {\n background-position: -16px -96px;\n}\n\n.ui-icon-document {\n background-position: -32px -96px;\n}\n\n.ui-icon-document-b {\n background-position: -48px -96px;\n}\n\n.ui-icon-note {\n background-position: -64px -96px;\n}\n\n.ui-icon-mail-closed {\n background-position: -80px -96px;\n}\n\n.ui-icon-mail-open {\n background-position: -96px -96px;\n}\n\n.ui-icon-suitcase {\n background-position: -112px -96px;\n}\n\n.ui-icon-comment {\n background-position: -128px -96px;\n}\n\n.ui-icon-person {\n background-position: -144px -96px;\n}\n\n.ui-icon-print {\n background-position: -160px -96px;\n}\n\n.ui-icon-trash {\n background-position: -176px -96px;\n}\n\n.ui-icon-locked {\n background-position: -192px -96px;\n}\n\n.ui-icon-unlocked {\n background-position: -208px -96px;\n}\n\n.ui-icon-bookmark {\n background-position: -224px -96px;\n}\n\n.ui-icon-tag {\n background-position: -240px -96px;\n}\n\n.ui-icon-home {\n background-position: 0 -112px;\n}\n\n.ui-icon-flag {\n background-position: -16px -112px;\n}\n\n.ui-icon-calendar {\n background-position: -32px -112px;\n}\n\n.ui-icon-cart {\n background-position: -48px -112px;\n}\n\n.ui-icon-pencil {\n background-position: -64px -112px;\n}\n\n.ui-icon-clock {\n background-position: -80px -112px;\n}\n\n.ui-icon-disk {\n background-position: -96px -112px;\n}\n\n.ui-icon-calculator {\n background-position: -112px -112px;\n}\n\n.ui-icon-zoomin {\n background-position: -128px -112px;\n}\n\n.ui-icon-zoomout {\n background-position: -144px -112px;\n}\n\n.ui-icon-search {\n background-position: -160px -112px;\n}\n\n.ui-icon-wrench {\n background-position: -176px -112px;\n}\n\n.ui-icon-gear {\n background-position: -192px -112px;\n}\n\n.ui-icon-heart {\n background-position: -208px -112px;\n}\n\n.ui-icon-star {\n background-position: -224px -112px;\n}\n\n.ui-icon-link {\n background-position: -240px -112px;\n}\n\n.ui-icon-cancel {\n background-position: 0 -128px;\n}\n\n.ui-icon-plus {\n background-position: -16px -128px;\n}\n\n.ui-icon-plusthick {\n background-position: -32px -128px;\n}\n\n.ui-icon-minus {\n background-position: -48px -128px;\n}\n\n.ui-icon-minusthick {\n background-position: -64px -128px;\n}\n\n.ui-icon-close {\n background-position: -80px -128px;\n}\n\n.ui-icon-closethick {\n background-position: -96px -128px;\n}\n\n.ui-icon-key {\n background-position: -112px -128px;\n}\n\n.ui-icon-lightbulb {\n background-position: -128px -128px;\n}\n\n.ui-icon-scissors {\n background-position: -144px -128px;\n}\n\n.ui-icon-clipboard {\n background-position: -160px -128px;\n}\n\n.ui-icon-copy {\n background-position: -176px -128px;\n}\n\n.ui-icon-contact {\n background-position: -192px -128px;\n}\n\n.ui-icon-image {\n background-position: -208px -128px;\n}\n\n.ui-icon-video {\n background-position: -224px -128px;\n}\n\n.ui-icon-script {\n background-position: -240px -128px;\n}\n\n.ui-icon-alert {\n background-position: 0 -144px;\n}\n\n.ui-icon-info {\n background-position: -16px -144px;\n}\n\n.ui-icon-notice {\n background-position: -32px -144px;\n}\n\n.ui-icon-help {\n background-position: -48px -144px;\n}\n\n.ui-icon-check {\n background-position: -64px -144px;\n}\n\n.ui-icon-bullet {\n background-position: -80px -144px;\n}\n\n.ui-icon-radio-off {\n background-position: -96px -144px;\n}\n\n.ui-icon-radio-on {\n background-position: -112px -144px;\n}\n\n.ui-icon-pin-w {\n background-position: -128px -144px;\n}\n\n.ui-icon-pin-s {\n background-position: -144px -144px;\n}\n\n.ui-icon-play {\n background-position: 0 -160px;\n}\n\n.ui-icon-pause {\n background-position: -16px -160px;\n}\n\n.ui-icon-seek-next {\n background-position: -32px -160px;\n}\n\n.ui-icon-seek-prev {\n background-position: -48px -160px;\n}\n\n.ui-icon-seek-end {\n background-position: -64px -160px;\n}\n\n.ui-icon-seek-start {\n background-position: -80px -160px;\n}\n\n/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */\n.ui-icon-seek-first {\n background-position: -80px -160px;\n}\n\n.ui-icon-stop {\n background-position: -96px -160px;\n}\n\n.ui-icon-eject {\n background-position: -112px -160px;\n}\n\n.ui-icon-volume-off {\n background-position: -128px -160px;\n}\n\n.ui-icon-volume-on {\n background-position: -144px -160px;\n}\n\n.ui-icon-power {\n background-position: 0 -176px;\n}\n\n.ui-icon-signal-diag {\n background-position: -16px -176px;\n}\n\n.ui-icon-signal {\n background-position: -32px -176px;\n}\n\n.ui-icon-battery-0 {\n background-position: -48px -176px;\n}\n\n.ui-icon-battery-1 {\n background-position: -64px -176px;\n}\n\n.ui-icon-battery-2 {\n background-position: -80px -176px;\n}\n\n.ui-icon-battery-3 {\n background-position: -96px -176px;\n}\n\n.ui-icon-circle-plus {\n background-position: 0 -192px;\n}\n\n.ui-icon-circle-minus {\n background-position: -16px -192px;\n}\n\n.ui-icon-circle-close {\n background-position: -32px -192px;\n}\n\n.ui-icon-circle-triangle-e {\n background-position: -48px -192px;\n}\n\n.ui-icon-circle-triangle-s {\n background-position: -64px -192px;\n}\n\n.ui-icon-circle-triangle-w {\n background-position: -80px -192px;\n}\n\n.ui-icon-circle-triangle-n {\n background-position: -96px -192px;\n}\n\n.ui-icon-circle-arrow-e {\n background-position: -112px -192px;\n}\n\n.ui-icon-circle-arrow-s {\n background-position: -128px -192px;\n}\n\n.ui-icon-circle-arrow-w {\n background-position: -144px -192px;\n}\n\n.ui-icon-circle-arrow-n {\n background-position: -160px -192px;\n}\n\n.ui-icon-circle-zoomin {\n background-position: -176px -192px;\n}\n\n.ui-icon-circle-zoomout {\n background-position: -192px -192px;\n}\n\n.ui-icon-circle-check {\n background-position: -208px -192px;\n}\n\n.ui-icon-circlesmall-plus {\n background-position: 0 -208px;\n}\n\n.ui-icon-circlesmall-minus {\n background-position: -16px -208px;\n}\n\n.ui-icon-circlesmall-close {\n background-position: -32px -208px;\n}\n\n.ui-icon-squaresmall-plus {\n background-position: -48px -208px;\n}\n\n.ui-icon-squaresmall-minus {\n background-position: -64px -208px;\n}\n\n.ui-icon-squaresmall-close {\n background-position: -80px -208px;\n}\n\n.ui-icon-grip-dotted-vertical {\n background-position: 0 -224px;\n}\n\n.ui-icon-grip-dotted-horizontal {\n background-position: -16px -224px;\n}\n\n.ui-icon-grip-solid-vertical {\n background-position: -32px -224px;\n}\n\n.ui-icon-grip-solid-horizontal {\n background-position: -48px -224px;\n}\n\n.ui-icon-gripsmall-diagonal-se {\n background-position: -64px -224px;\n}\n\n.ui-icon-grip-diagonal-se {\n background-position: -80px -224px;\n}\n\n/* Misc visuals\n----------------------------------*/\n\n/* Corner radius */\n.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl {\n -moz-border-radius-topleft: 0px;\n -webkit-border-top-left-radius: 0px;\n -khtml-border-top-left-radius: 0px;\n border-top-left-radius: 0px;\n}\n\n.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr {\n -moz-border-radius-topright: 0px;\n -webkit-border-top-right-radius: 0px;\n -khtml-border-top-right-radius: 0px;\n border-top-right-radius: 0px;\n}\n\n.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl {\n -moz-border-radius-bottomleft: 0px;\n -webkit-border-bottom-left-radius: 0px;\n -khtml-border-bottom-left-radius: 0px;\n border-bottom-left-radius: 0px;\n}\n\n.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br {\n -moz-border-radius-bottomright: 0px;\n -webkit-border-bottom-right-radius: 0px;\n -khtml-border-bottom-right-radius: 0px;\n border-bottom-right-radius: 0px;\n}\n\n/* Overlays */\n.ui-widget-overlay {\n background: #aaaaaa url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAh0lEQVRYhe2UsQ3AIAwEL0zC/qMwhTdJiiCRpH2kfPHu0DUnbN0xxjiZU1U8p/f+ev/Bm7MccAu6ygE0ZzlgrdhRrqqWoKMczB90lQNoznLwuUE3uXRwB08HVZ4OqjwdVHk6qPJ0UOXpoMrTQZWngypPB1WeDqo8HVR5OqjydFDl6aDK7Tt4AWXCW8vnTP6PAAAAAElFTkSuQmCC\") 50% 50% repeat;\n opacity: .30;\n filter: Alpha(Opacity = 30);\n}\n\n.ui-widget-shadow {\n margin: -8px 0 0 -8px;\n padding: 8px;\n background: #aaaaaa url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAABkCAYAAAD0ZHJ6AAAAe0lEQVRoge3OMQHAIBAAMcC/kjdZJHTI0A4XBdkz86wfO18H3hRUBVVBVVAVVAVVQVVQFVQFVUFVUBVUBVVBVVAVVAVVQVVQFVQFVUFVUBVUBVVBVVAVVAVVQVVQFVQFVUFVUBVUBVVBVVAVVAVVQVVQFVQFVUFVUBVUF8O8A8WdY6opAAAAAElFTkSuQmCC\") 50% 50% repeat-x;\n opacity: .30;\n filter: Alpha(Opacity = 30);\n -moz-border-radius: 8px;\n -khtml-border-radius: 8px;\n -webkit-border-radius: 8px;\n border-radius: 8px;\n}\n\n/*!\n* jQuery UI Resizable 1.8.21\n*\n* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n* Dual licensed under the MIT or GPL Version 2 licenses.\n* http://jquery.org/license\n*\n* http://docs.jquery.com/UI/Resizable#theming\n*/\n.ui-resizable {\n position: relative;\n}\n\n.ui-resizable-handle {\n position: absolute;\n font-size: 0.1px;\n display: block;\n}\n\n.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle {\n display: none;\n}\n\n.ui-resizable-n {\n cursor: n-resize;\n height: 7px;\n width: 100%;\n top: -5px;\n left: 0;\n}\n\n.ui-resizable-s {\n cursor: s-resize;\n height: 7px;\n width: 100%;\n bottom: -5px;\n left: 0;\n}\n\n.ui-resizable-e {\n cursor: e-resize;\n width: 7px;\n right: -5px;\n top: 0;\n height: 100%;\n}\n\n.ui-resizable-w {\n cursor: w-resize;\n width: 7px;\n left: -5px;\n top: 0;\n height: 100%;\n}\n\n.ui-resizable-se {\n cursor: se-resize;\n width: 12px;\n height: 12px;\n right: 1px;\n bottom: 1px;\n}\n\n.ui-resizable-sw {\n cursor: sw-resize;\n width: 9px;\n height: 9px;\n left: -5px;\n bottom: -5px;\n}\n\n.ui-resizable-nw {\n cursor: nw-resize;\n width: 9px;\n height: 9px;\n left: -5px;\n top: -5px;\n}\n\n.ui-resizable-ne {\n cursor: ne-resize;\n width: 9px;\n height: 9px;\n right: -5px;\n top: -5px;\n}\n\n/*!\n* jQuery UI Button 1.8.21\n*\n* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n* Dual licensed under the MIT or GPL Version 2 licenses.\n* http://jquery.org/license\n*\n* http://docs.jquery.com/UI/Button#theming\n*/\n.ui-button {\n display: inline-block;\n position: relative;\n padding: 0;\n margin-right: .1em;\n text-decoration: none !important;\n cursor: pointer;\n text-align: center;\n zoom: 1;\n overflow: visible;\n}\n\n/* the overflow property removes extra width in IE */\n.ui-button-icon-only {\n width: 2.2em;\n}\n\n/* to make room for the icon, a width needs to be set here */\nbutton.ui-button-icon-only {\n width: 2.4em;\n}\n\n/* button elements seem to need a little more width */\n.ui-button-icons-only {\n width: 3.4em;\n}\n\nbutton.ui-button-icons-only {\n width: 3.7em;\n}\n\n/*button text element */\n.ui-button .ui-button-text {\n display: block;\n line-height: 1.4;\n}\n\n.ui-button-text-only .ui-button-text {\n padding: .4em 1em;\n}\n\n.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text {\n padding: .4em;\n text-indent: -9999999px;\n}\n\n.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text {\n padding: .4em 1em .4em 2.1em;\n}\n\n.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text {\n padding: .4em 2.1em .4em 1em;\n}\n\n.ui-button-text-icons .ui-button-text {\n padding-left: 2.1em;\n padding-right: 2.1em;\n}\n\n/* no icon support for input elements, provide padding by default */\ninput.ui-button {\n padding: .4em 1em;\n}\n\n/*button icon element(s) */\n.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon {\n position: absolute;\n top: 50%;\n margin-top: -8px;\n}\n\n.ui-button-icon-only .ui-icon {\n left: 50%;\n margin-left: -8px;\n}\n\n.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary {\n left: .5em;\n}\n\n.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary {\n right: .5em;\n}\n\n.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary {\n right: .5em;\n}\n\n/*button sets*/\n.ui-buttonset {\n margin-right: 7px;\n}\n\n.ui-buttonset .ui-button {\n margin-left: 0;\n margin-right: -.3em;\n}\n\n/* workarounds */\nbutton.ui-button::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n/* reset extra padding in Firefox */\n/*!\n * jQuery UI Dialog 1.8.21\n *\n * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * http://docs.jquery.com/UI/Dialog#theming\n */\n.ui-dialog {\n position: absolute;\n padding: .2em;\n width: 300px;\n overflow: hidden;\n}\n\n.ui-dialog .ui-dialog-titlebar {\n padding: .4em 1em;\n position: relative;\n}\n\n.ui-dialog .ui-dialog-title {\n float: left;\n margin: .1em 16px .1em 0;\n}\n\n.ui-dialog .ui-dialog-titlebar-close {\n position: absolute;\n right: .3em;\n top: 50%;\n width: 19px;\n margin: -10px 0 0 0;\n padding: 1px;\n height: 18px;\n}\n\n.ui-dialog .ui-dialog-titlebar-close span {\n display: block;\n margin: 1px;\n}\n\n.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus {\n padding: 0;\n}\n\n.ui-dialog .ui-dialog-content {\n position: relative;\n border: 0;\n padding: .5em;\n background: none;\n overflow: auto;\n zoom: 1;\n}\n\n.ui-dialog .ui-dialog-buttonpane {\n text-align: left;\n border-width: 1px 0 0 0;\n background-image: none;\n margin: .5em 0 0 0;\n padding: .3em 1em .5em .4em;\n}\n\n.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {\n float: right;\n}\n\n.ui-dialog .ui-dialog-buttonpane button {\n margin: .5em .4em .5em 0;\n cursor: pointer;\n}\n\n.ui-dialog .ui-resizable-se {\n width: 14px;\n height: 14px;\n right: 3px;\n bottom: 3px;\n}\n\n.ui-draggable .ui-dialog-titlebar {\n cursor: move;\n}\n\n/*!\n* jQuery UI Tabs 1.8.21\n*\n* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n* Dual licensed under the MIT or GPL Version 2 licenses.\n* http://jquery.org/license\n*\n* http://docs.jquery.com/UI/Tabs#theming\n*/\n.ui-tabs {\n position: relative;\n padding: 0em;\n zoom: 1;\n}\n\n/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as \"fixed\") */\n.ui-tabs .ui-tabs-nav {\n margin: 0;\n padding: .2em .2em 0;\n}\n\n.ui-tabs .ui-tabs-nav li {\n list-style: none;\n float: left;\n position: relative;\n top: 1px;\n margin: 0 .2em 1px 0;\n border-bottom: 0 !important;\n padding: 0;\n white-space: nowrap;\n}\n\n.ui-tabs .ui-tabs-nav li a {\n float: left;\n padding: .2em 1em;\n text-decoration: none;\n}\n\n.ui-tabs .ui-tabs-nav li.ui-tabs-active {\n margin-bottom: 0;\n padding-bottom: 1px;\n}\n\n.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a {\n cursor: text;\n}\n\n.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a {\n cursor: pointer;\n}\n\n/* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */\n.ui-tabs .ui-tabs-panel {\n display: block;\n border-width: 0;\n padding: 0em 0.1em;\n background: none;\n}\n\n/*!\n* jQuery UI Progressbar 1.8.21\n*\n* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)\n* Dual licensed under the MIT or GPL Version 2 licenses.\n* http://jquery.org/license\n*\n* http://docs.jquery.com/UI/Progressbar#theming\n*/\n.ui-progressbar {\n height: 5px;\n text-align: left;\n overflow: hidden;\n}\n\n.ui-progressbar .ui-progressbar-value {\n margin: -1px;\n height: 100%;\n}");
  3789. // var LF = "";
  3790. if(database.settings.smallFont.value) GM_addStyle("#SITRBoard {font-size:8pt}");
  3791. };
  3792. /***********************************************************************************************************************
  3793. * ikariam
  3794. **********************************************************************************************************************/
  3795.  
  3796. var ikariam = {
  3797. _View : null,
  3798. _Host : null,
  3799. _Server : null,
  3800. _ActionRequest : null,
  3801. _Units : null,
  3802. _BuildingsList : null,
  3803. _AltBuildingsList : null,
  3804. _Nationality : null,
  3805. _GameVersion : null,
  3806. _TemplateView : null,
  3807. _currentCity : null,
  3808. url : function() {
  3809. return 'http://' + this.Host() + '/index.php'
  3810. },
  3811. get mainView() {
  3812. return unsafeWindow.ikariam.backgroundView.id
  3813. },
  3814. get boxViewParams() {
  3815. if(unsafeWindow.ikariam.mainbox_x || unsafeWindow.ikariam.mainbox_y || unsafeWindow.ikariam.mainbox_z) {
  3816. return {
  3817. mainbox_x: unsafeWindow.ikariam.mainbox_x,
  3818. mainbox_y: unsafeWindow.ikariam.mainbox_y,
  3819. mainbox_z: unsafeWindow.ikariam.mainbox_z
  3820. };
  3821. }
  3822. return {};
  3823. },
  3824. loadUrl : function(ajax, mainView, params) {
  3825. mainView = mainView || ikariam.mainView;
  3826. var paramList = {cityId: ikariam.CurrentCityId};
  3827. if(ikariam.CurrentCityId !== params.cityId) {
  3828. paramList.action = 'header';
  3829. paramList.function = 'changeCurrentCity';
  3830. paramList.actionRequest = unsafeWindow.ikariam.model.actionRequest;
  3831. paramList.currentCityId = ikariam.CurrentCityId;
  3832. paramList.oldView = ikariam.mainView
  3833.  
  3834. }
  3835.  
  3836. if(mainView !== undefined && mainView !== ikariam.mainView) {
  3837. paramList.oldBackgroundView = ikariam.mainView;
  3838. paramList.backgroundView = mainView;
  3839. ajax = false;
  3840. }
  3841. $.extend(paramList, params);
  3842. if(ajax) {
  3843. gotoAjaxURL('?' + $.map(paramList,function(value, key) {
  3844. return key + '=' + value;
  3845. }).join('&'))
  3846. } else {
  3847. gotoURL(ikariam.url() + '?' + $.map(paramList,function(value, key) {
  3848. return key + '=' + value;
  3849. }).join('&'))
  3850. }
  3851.  
  3852. function gotoURL(url) {
  3853. window.location.assign(url)
  3854. }
  3855.  
  3856. function gotoAjaxURL(url) {
  3857. document.location = 'javascript:ajaxHandlerCall(' + JSON.stringify(url) + '); void(0);';
  3858. }
  3859. },
  3860. Host : function() {
  3861. if(this._Host == null) {
  3862. this._Host = '';
  3863. this._Host = document.location.host;
  3864. }
  3865. return this._Host;
  3866. },
  3867. Server : function(host) {
  3868. if(this._Server == null) {
  3869. if(host == undefined) {
  3870. host = this.Host();
  3871. }
  3872. this._Server = '';
  3873. var parts = host.split(".");
  3874. var idx = 0;
  3875. if(parts[0] == 'www') {
  3876. idx++;
  3877. }
  3878. this._Server = parts[idx];
  3879. }
  3880. return this._Server;
  3881. },
  3882. Nationality : function(host) {
  3883. if(this._Nationality == null) {
  3884. if(host == undefined) {
  3885. host = this.Host();
  3886. }
  3887. this._Nationality = '';
  3888. var parts = host.split(".");
  3889. var idx = (parts[0] == 'www') ? 2 : 1;
  3890. this._Nationality = parts[idx];
  3891. }
  3892. return this._Nationality;
  3893. },
  3894. getNextWineTick : function(precision) {
  3895. precision = precision || 1; // 1 for Mins, 2 for mins:secs
  3896. if(precision == 1) {
  3897. return 60 - new Date().getMinutes();
  3898. } else {
  3899. var secs = 3600 - (new Date().getMinutes() * 60) - new Date().getSeconds();
  3900. var ret = Math.floor(secs / 60) + database.getGlobalData.getLocalisedString('minute') + ' ';
  3901. ret += secs - (Math.floor(secs / 60) * 60) + database.getGlobalData.getLocalisedString('second');
  3902. return ret;
  3903. }
  3904. },
  3905. GameVersion : function() {
  3906. if(this._GameVersion == null) {
  3907. this._GameVersion = $('span.version a span').text().split("v ")[1];
  3908. }
  3909. return this._GameVersion
  3910. },
  3911. get CurrentCityId() {
  3912. return unsafeWindow.ikariam.backgroundView && unsafeWindow.ikariam.backgroundView.id === 'city' ? ikariam._currentCity || unsafeWindow.ikariam.model.relatedCityData[unsafeWindow.ikariam.model.relatedCityData.selectedCity].id : unsafeWindow.ikariam.model.relatedCityData[unsafeWindow.ikariam.model.relatedCityData.selectedCity].id
  3913. },
  3914. get viewIsCity() {
  3915. return unsafeWindow.ikariam.backgroundView && unsafeWindow.ikariam.backgroundView.id === 'city'
  3916. },
  3917. get viewIsIsland() {
  3918. return unsafeWindow.ikariam.backgroundView && unsafeWindow.ikariam.backgroundView.id === 'island'
  3919. },
  3920. get viewIsWorld() {
  3921. return unsafeWindow.ikariam.backgroundView && unsafeWindow.ikariam.backgroundView.id === 'worldmap_iso'
  3922. },
  3923. get getCurrentCity() {
  3924. return database.cities[ikariam.CurrentCityId];
  3925. },
  3926. get getCapital() {
  3927. for(var c in database.cities) {
  3928. if(database.cities[c].isCapital) {
  3929. return database.cities[c];
  3930. }
  3931. }
  3932. return false;
  3933. },
  3934. get CurrentTemplateView() {
  3935. try {
  3936. this._CurrentTemplateView = unsafeWindow.ikariam.templateView.id;
  3937. } catch(e) {
  3938. this._CurrentTemplateView = null
  3939. }
  3940. return this._CurrentTemplateView;
  3941. },
  3942. getLocalizationStrings : function() {
  3943. var localStrings = unsafeWindow.LocalizationStrings;
  3944. if(!localStrings) {
  3945. $('script').each(function(index, script) {
  3946. var match = /LocalizationStrings = JSON.parse\('(.*)'\);/.exec(script.innerHTML);
  3947. if(match) {
  3948. localStrings = JSON.parse(match[1]);
  3949. return false;
  3950. }
  3951. });
  3952. }
  3953. var local = $.extend({}, localStrings);
  3954. //merge ikariams time units
  3955. $.extend(local, local['timeunits']['short']);
  3956. //remove extra objects
  3957. delete local['warnings'];
  3958. delete local['timeunits'];
  3959. $.each(local, function(name, value) {
  3960. database.getGlobalData.addLocalisedString(name.toLowerCase(), value)
  3961. });
  3962.  
  3963. local = null;
  3964. database.getGlobalData.addLocalisedString('Military', $('#js_GlobalMenu_military').find('span').text());
  3965. database.getGlobalData.addLocalisedString('Options', $('#GF_toolbar').find('ul li.options a').attr('title'));
  3966. database.getGlobalData.addLocalisedString('Economy', $('#js_GlobalMenu_cities').find('span').text());
  3967. database.getGlobalData.addLocalisedString('Research', $('#js_GlobalMenu_research').find('span').text());
  3968. },
  3969. setupEventHandlers : function() {
  3970. events('ajaxResponse').sub(function(response) {
  3971. var view, html, data, template;
  3972. var len = response.length;
  3973. var oldCity = this._currentCity;
  3974. while(len) {
  3975. len--;
  3976. switch(response[len][0]) {
  3977. case 'updateGlobalData':
  3978. this._currentCity = parseInt(response[len][1]["backgroundData"].id);
  3979. var cityData = $.extend({}, response[len][1]["backgroundData"], response[len][1]["headerData"]);
  3980. events('updateCityData').pub(this.CurrentCityId, $.extend({}, cityData));
  3981. events('updateBuildingData').pub(this.CurrentCityId, cityData.position);
  3982. break;
  3983. case 'changeView':
  3984. view = response[len][1][0];
  3985. html = response[len][1][1];
  3986. break;
  3987. case 'updateTemplateData':
  3988. template = response[len][1];
  3989. if(unsafeWindow.ikariam.templateView) {
  3990. if(unsafeWindow.ikariam.templateView.id == 'researchAdvisor') {
  3991. view = unsafeWindow.ikariam.templateView.id
  3992. }
  3993. }
  3994. break;
  3995. case 'updateBackgroundData':
  3996. oldCity = this.CurrentCityId;
  3997. this._currentCity = parseInt(response[len][1].id);
  3998. events('updateCityData').pub(this._currentCity, $.extend(true, {}, unsafeWindow.dataSetForView, response[len][1]));
  3999. events('updateBuildingData').pub(this._currentCity, response[len][1].position);
  4000. break;
  4001. }
  4002. }
  4003.  
  4004. this.parseViewData(view, html, template);
  4005. if(oldCity !== this.CurrentCityId) {
  4006. events('cityChanged').pub(this.CurrentCityId)
  4007. }
  4008. }.bind(ikariam));
  4009. //parse data on form submit and add it when submit success
  4010. events('formSubmit').sub(function(form) {
  4011. var formID = form.getAttribute('id');
  4012. if(!ikariam[formID + 'Submitted'])return false;
  4013. var formSubmission = (function formSubmit() {
  4014. var data = ikariam[formID + 'Submitted']();
  4015. return function formSubmitID(response) {
  4016. var len = response.length;
  4017. var feedback = 0;
  4018. while(len) {
  4019. len--;
  4020. if(response[len][0] == 'provideFeedback')
  4021. feedback = response[len][1][0].type;
  4022. }
  4023. if(feedback == 10) //success
  4024. ikariam[formID + 'Submitted'](data);
  4025. events('ajaxResponse').unsub(formSubmission);
  4026. }
  4027. })();
  4028. events('ajaxResponse').sub(formSubmission)
  4029. }.bind(ikariam));
  4030. events(Constant.Events.CITYDATA_AVAILABLE).sub(ikariam.FetchAllTowns.bind(ikariam))
  4031. },
  4032. Init : function() {
  4033. this.setupEventHandlers();
  4034. },
  4035. parseViewData : function(view, html, tData) {
  4036. if(this.getCurrentCity) {
  4037. switch(view) {
  4038. case 'finances':
  4039. this.parseFinances($('#finances').find('table.table01 tr').slice(2).children('td'));
  4040. break;
  4041. case Constant.Buildings.TOWN_HALL:
  4042. this.parseTownHall(tData);
  4043. break;
  4044. case 'militaryAdvisor':
  4045. this.parseMilitaryAdvisor(html, tData);
  4046. break;
  4047. case 'cityMilitary':
  4048. this.parseCityMilitary();
  4049. this.parseMilitaryLocalization();
  4050. break;
  4051. case 'researchAdvisor':
  4052. this.parseResearchAdvisor(tData);
  4053. break;
  4054. case Constant.Buildings.PALACE:
  4055. this.parsePalace();
  4056. break;
  4057. case Constant.Buildings.ACADEMY:
  4058. this.parseAcademy(tData);
  4059. break;
  4060. case 'culturalPossessions_assign':
  4061. this.parseCulturalPossessions(html);
  4062. break;
  4063. case Constant.Buildings.MUSEUM:
  4064. this.parseMuseum();
  4065. break;
  4066. case Constant.Buildings.TAVERN:
  4067. this.parseTavern();
  4068. break;
  4069. case 'transport':
  4070. //this.transportFormSubmitted();
  4071. break;
  4072. case Constant.Buildings.TEMPLE:
  4073. this.parseTemple(tData);
  4074. break;
  4075. case Constant.Buildings.BLACKMARKET:
  4076. break;
  4077. case Constant.Buildings.MARINECHARTARCHIVE:
  4078. break;
  4079. case Constant.Buildings.BARRACKS:
  4080. case Constant.Buildings.SHIPYARD:
  4081. this.parseBarracks(view, html, tData);
  4082. break;
  4083. case 'deployment':
  4084. this.parseMilitaryTransport();
  4085. break;
  4086. case 'premium':
  4087. this.parsePremium(view, html, tData);
  4088. break;
  4089. }
  4090. }
  4091. },
  4092. parsePalace : function() {
  4093. var governmentType = $('#formOfRuleContent').find('td.government_pic img').attr('src').slice(16, -8);
  4094. var changed = (database.getGlobalData.getGovernmentType != governmentType);
  4095. database.getGlobalData.governmentType = governmentType;
  4096. if(changed) events(Constant.Events.GLOBAL_UPDATED).pub({type: 'government'})
  4097. },
  4098. parseCulturalPossessions : function(html) {
  4099. var allCulturalGoods = html.match(/iniValue\s:\s(\d*)/g);
  4100. var changes = [];
  4101. $.each(html.match(/goodscity_(\d*)/g), function(i) {
  4102. var cityID = this.split('_')[1];
  4103. var culturalGoods = parseInt(allCulturalGoods[i].split(' ').pop());
  4104. var changed = (database.cities[cityID]._culturalGoods != culturalGoods);
  4105. if(changed) {
  4106. database.cities[cityID]._culturalGoods = culturalGoods;
  4107. changes.push(cityID)
  4108. }
  4109. });
  4110. if(changes.length) $.each(changes, function(idx, cityID) {
  4111. events(Constant.Events.CITY_UPDATED).pub(cityID, {culturalGoods: true})
  4112. });
  4113. database.getGlobalData.addLocalisedString('Cultural Goods', $('#js_mainBoxHeaderTitle').text())
  4114. },
  4115. parseMuseum : function() {
  4116. var regText = $('#val_culturalGoodsDeposit').parent().text().match(/(\d+)/g);
  4117. if(regText.length == 2) {
  4118. var changed = ikariam.getCurrentCity.updateCulturalGoods(parseInt(regText[0]))
  4119. }
  4120. if(changed) events(Constant.Events.CITY_UPDATED).pub(ikariam.CurrentCityId, {culturalGoods: true})
  4121. },
  4122. parseTavern : function() {
  4123. },
  4124. resTransportObject : function() {
  4125. return {id : null,
  4126. wood : 0,
  4127. wine : 0,
  4128. marble : 0,
  4129. glass : 0,
  4130. sulfur : 0,
  4131. targetCityId: 0,
  4132. arrivalTime : 0,
  4133. originCityId: 0,
  4134. loadedTime : 0,
  4135. mission : ''};
  4136. },
  4137. troopTransportObject : function() {
  4138. return {id : null,
  4139. troops : {},
  4140. targetCityId: 0,
  4141. arrivalTime : 0,
  4142. originCityId: 0,
  4143. returnTime : 0,
  4144. mission : ''};
  4145. },
  4146. parseBarracks : function(view, html, tData) {
  4147. var type = view == Constant.Buildings.BARRACKS ? 'army' : view == Constant.Buildings.SHIPYARD ? 'fleet' : false;
  4148. var city = ikariam.getCurrentCity;
  4149. var currentUnits = {};
  4150. var i = 14;
  4151. while(i--) {
  4152. if(tData['js_barracksUnitUnitsAvailable' + (i - 1)]) {
  4153. currentUnits[tData['js_barracksUnitClass' + (i - 1)]['class'].split(' ').pop()] = parseInt(tData['js_barracksUnitUnitsAvailable' + (i - 1)].text)
  4154. }
  4155. }
  4156. var changes = city.military.updateUnits(currentUnits);
  4157.  
  4158. var elem = $('#unitConstructionList');
  4159. if(elem.length) {
  4160. var tasks = [];
  4161. tasks.push({
  4162. units : parseUnits(elem.find('> .army_wrapper .army')),
  4163. completionTime: parseTime($('#buildCountDown').text()),
  4164. type : type
  4165. });
  4166. elem.find('div.constructionBlock').each(function() {
  4167. tasks.push({
  4168. units : parseUnits($(this).find('> .army_wrapper .army')),
  4169. completionTime: parseTime($(this).find('h4 > span').text()),
  4170. type : type
  4171. })
  4172. });
  4173. changes = changes.concat(city.military.setTraining(tasks))
  4174. }
  4175.  
  4176. elem = null;
  4177. if(changes.length) {
  4178. events(Constant.Events.MILITARY_UPDATED).pub(city.getId, $.exclusive(changes))
  4179. }
  4180.  
  4181. function parseUnits(element) {
  4182. var units = {};
  4183. element.each(function() {
  4184. units[Constant.unitIds[this.classList.toString().match(/(\d+)/g)]] = parseInt(this.nextElementSibling.textContent.match(/(\d+)/g))
  4185. });
  4186. return units;
  4187. }
  4188.  
  4189. function parseTime(timeText) {
  4190. var completionTime = new Date();
  4191. completionTime.setSeconds(completionTime.getSeconds() + (
  4192. timeText.match(/(\d+)s/) ? parseInt(timeText.match(/(\d+)s/)[1]) : 0));
  4193. completionTime.setMinutes(completionTime.getMinutes() + (
  4194. timeText.match(/(\d+)m/) ? parseInt(timeText.match(/(\d+)m/)[1]) : 0));
  4195. completionTime.setHours(completionTime.getHours() + (
  4196. timeText.match(/(\d+)h/) ? parseInt(timeText.match(/(\d+)h/)[1]) : 0));
  4197. completionTime.setDate(completionTime.getDate() + (
  4198. timeText.match(/(\d+)D/) ? parseInt(timeText.match(/(\d+)D/)[1]) : 0));
  4199. return completionTime.getTime();
  4200. }
  4201. },
  4202. /**
  4203. * First call without data will parse the transportform, seccond call will add the forms data to the database
  4204. */
  4205. transportFormSubmitted : function(data) {
  4206. try {
  4207. if(!data) {
  4208. var journeyTime = $('#journeyTime').text();
  4209. var loadingTime = $('#loadingTime').text();
  4210. var wood = parseInt($('#textfield_wood').val());
  4211. var wine = parseInt($('#textfield_wine').val());
  4212. var marble = parseInt($('#textfield_marble').val());
  4213. var glass = parseInt($('#textfield_glass').val());
  4214. var sulfur = parseInt($('#textfield_sulfur').val());
  4215. var targetID = $('input[name=destinationCityId]').val();
  4216. var ships = $('#transporterCount').val();
  4217. var arrTime = new Date();
  4218. var loadedTime = new Date();
  4219.  
  4220. arrTime.setSeconds(arrTime.getSeconds() + (
  4221. journeyTime.match(/(\d+)s/) ? parseInt(journeyTime.match(/(\d+)s/)[1]) : 0));
  4222. arrTime.setMinutes(arrTime.getMinutes() + (
  4223. journeyTime.match(/(\d+)m/) ? parseInt(journeyTime.match(/(\d+)m/)[1]) : 0));
  4224. arrTime.setHours(arrTime.getHours() + (
  4225. journeyTime.match(/(\d+)h/) ? parseInt(journeyTime.match(/(\d+)h/)[1]) : 0));
  4226. arrTime.setDate(arrTime.getDate() + (
  4227. journeyTime.match(/(\d+)D/) ? parseInt(journeyTime.match(/(\d+)D/)[1]) : 0));
  4228.  
  4229. loadedTime.setSeconds(loadedTime.getSeconds() + (
  4230. loadingTime.match(/(\d+)s/) ? parseInt(loadingTime.match(/(\d+)s/)[1]) : 0));
  4231. loadedTime.setMinutes(loadedTime.getMinutes() + (
  4232. loadingTime.match(/(\d+)m/) ? parseInt(loadingTime.match(/(\d+)m/)[1]) : 0));
  4233. loadedTime.setHours(loadedTime.getHours() + (
  4234. loadingTime.match(/(\d+)h/) ? parseInt(loadingTime.match(/(\d+)h/)[1]) : 0));
  4235. loadedTime.setDate(loadedTime.getDate() + (
  4236. loadingTime.match(/(\d+)D/) ? parseInt(loadingTime.match(/(\d+)D/)[1]) : 0));
  4237.  
  4238. return new Movement('XXX-' + arrTime.getTime(), this.CurrentCityId, targetID, arrTime.getTime(), 'transport', loadedTime.getTime(), { wood: wood || 0, wine: wine || 0, marble: marble || 0, glass: glass || 0, sulfur: sulfur || 0}, undefined, ships)
  4239. } else {
  4240. database.getGlobalData.addFleetMovement(data);
  4241. events(Constant.Events.MOVEMENTS_UPDATED).pub([data.getTargetCityId]);
  4242. //events(Constant.Events.RESOURCES_UPDATED).pub(data.getOriginCityId)
  4243. }
  4244. } catch(e) {
  4245. SITR.error('transportFormSubmitted', e);
  4246. } finally {
  4247. }
  4248. },
  4249. parseMilitaryTransport : function(submit) {
  4250. //$('ul.assignUnits li input.textfield')
  4251. return false;
  4252. submit = submit || false;
  4253. var that = this;
  4254. if(submit) {
  4255. var journeyTime = $('#journeyTime').text();
  4256. var returnTime = $('#returnTime').text();
  4257. var targetID = $('input:[name=destinationCityId]').val();
  4258. var troops = {};
  4259. var mission = '';
  4260. $('ul.assignUnits li input.textfield').each(function() {
  4261. if(this.value !== 0) {
  4262. troops[this.getAttribute('name').split('_').pop()] = parseInt(this.value)
  4263. }
  4264. if(mission === '') {
  4265. mission = 'deploy' + this.getAttribute('name').match(/_(.*)_/)[1]
  4266. }
  4267. });
  4268. var arrTime = new Date();
  4269. var transport = this.troopTransportObject();
  4270. transport.id = 'XXX-' + arrTime.getTime();
  4271. transport.targetCityId = targetID;
  4272. transport.originCityId = this.CurrentCityId;
  4273. transport.mission = mission;
  4274. transport.troops = troops;
  4275. arrTime.setSeconds(arrTime.getSeconds() + (journeyTime.match(/(\d+)s/) ? parseInt(journeyTime.match(/(\d+)s/)[1]) : 0));
  4276. arrTime.setMinutes(arrTime.getMinutes() + (journeyTime.match(/(\d+)m/) ? parseInt(journeyTime.match(/(\d+)m/)[1]) : 0));
  4277. arrTime.setHours(arrTime.getHours() + (journeyTime.match(/(\d+)h/) ? parseInt(journeyTime.match(/(\d+)h/)[1]) : 0));
  4278. arrTime.setDate(arrTime.getDate() + (journeyTime.match(/(\d+)D/) ? parseInt(journeyTime.match(/(\d+)D/)[1]) : 0));
  4279. transport.arrivalTime = arrTime.getTime();
  4280. arrTime = new Date();
  4281. arrTime.setSeconds(arrTime.getSeconds() + (returnTime.match(/(\d+)s/) ? parseInt(returnTime.match(/(\d+)s/)[1]) : 0));
  4282. arrTime.setMinutes(arrTime.getMinutes() + (returnTime.match(/(\d+)m/) ? parseInt(returnTime.match(/(\d+)m/)[1]) : 0));
  4283. arrTime.setHours(arrTime.getHours() + (returnTime.match(/(\d+)h/) ? parseInt(returnTime.match(/(\d+)h/)[1]) : 0));
  4284. arrTime.setDate(arrTime.getDate() + (returnTime.match(/(\d+)D/) ? parseInt(returnTime.match(/(\d+)D/)[1]) : 0));
  4285. transport.returnTime = arrTime.getTime();
  4286. database.getGlobalData.addFleetMovement(transport);
  4287. render.toast('Updated: Movement added');
  4288. } else {
  4289. return true
  4290. }
  4291. },
  4292. parseFinances : function($elem) {
  4293. var updateTime = $.now();
  4294.  
  4295. for(var i = 1; i < database.getCityCount + 1; i++) {
  4296. var city = database.cities[Object.keys(database.cities)[i - 1]];
  4297. if(city != false) {
  4298. var changed = city.updateIncome(parseInt($elem[(i * 4) - 3].textContent.split(database.getGlobalData.getLocalisedString('thousandSeperator')).join('')));
  4299. changed = city.updateExpenses(parseInt($elem[(i * 4) - 2].textContent.split(database.getGlobalData.getLocalisedString('thousandSeperator')).join(''))) || changed;
  4300. }
  4301. if(changed) events(Constant.Events.CITY_UPDATED).pub(city.getId, {finances: true});
  4302. //database.getGlobalData.SigmaIncome = parseInt($elem[(Object.keys(database.cities).length * 4) + 1].textContent.split(database.getGlobalData.getLocalisedString('thousandSeperator')).join(''));
  4303. //database.getGlobalData.SigmaExpenses = -1 * parseInt($elem[(Object.keys(database.cities).length * 4) + 2].textContent.split(database.getGlobalData.getLocalisedString('thousandSeperator')).join(''));
  4304. }
  4305. var $breakdown = $('#finances').find('tbody tr.bottomLine td:last-child');
  4306. database.getGlobalData.finance.armyCost = parseInt($breakdown[0].textContent.split(database.getGlobalData.getLocalisedString('thousandSeperator')).join(''));
  4307. database.getGlobalData.finance.fleetCost = parseInt($breakdown[1].textContent.split(database.getGlobalData.getLocalisedString('thousandSeperator')).join(''));
  4308. database.getGlobalData.finance.armySupply = parseInt($breakdown[2].textContent.split(database.getGlobalData.getLocalisedString('thousandSeperator')).join(''));
  4309. database.getGlobalData.finance.fleetSupply = parseInt($breakdown[3].textContent.split(database.getGlobalData.getLocalisedString('thousandSeperator')).join(''));
  4310. events('globalData').pub({finances: true})
  4311. },
  4312. parseResearchAdvisor : function(data) {
  4313. var changes = [];
  4314. var research = JSON.parse(data['new_js_params'] || data['load_js'].params).currResearchType;
  4315. $.each(research, function(name, Data) {
  4316. var id = parseInt(Data.aHref.match(/researchId=([0-9]+)/i)[1]);
  4317. var level = name.match(/\((\d+)\)/);
  4318. var explored = level ? parseInt(level[1]) - 1 : (Data.liClass === 'explored' ? 1 : 0);
  4319. var changed = database.getGlobalData.updateResearchTopic(id, explored);
  4320. if(changed) changes.push({type: 'research_topic', subType: id});
  4321. database.getGlobalData.addLocalisedString('research_' + id, name.split('(').shift())
  4322. });
  4323. // if (Object.keys(database.getGlobalData.research.topics).length > 66) {
  4324. // database.getGlobalData.research.lastUpdate = $.now();
  4325. // }
  4326. if(changes.length) events(Constant.Events.GLOBAL_UPDATED).pub(changes);
  4327. database.getGlobalData.addLocalisedString('researchpoints', $('li.points').text().split(':')[0]);
  4328. },
  4329. parseAcademy : function(data) {
  4330. var city = ikariam.getCurrentCity;
  4331. var changed = city.updateResearchers(parseInt(data.js_AcademySlider.slider.ini_value));
  4332. if(changed)
  4333. events(Constant.Events.CITY_UPDATED).pub(city.getId, {research: changed});
  4334. //database.getGlobalData.addLocalisedString('scientists', $('#setScientists').find('.scientists').text().text().split(':')[0])
  4335. },
  4336. parseTownHall : function(data) {
  4337. var changes = {};
  4338. var city = ikariam.getCurrentCity;
  4339. var cultBon = parseInt(data['js_TownHallSatisfactionOverviewCultureBoniTreatyBonusValue'].text) || 0;
  4340. var priests = parseInt(data['js_TownHallPopulationGraphPriestCount'].text) || 0;
  4341. var researchers = parseInt(data['js_TownHallPopulationGraphScientistCount'].text) || 0;
  4342. changes['culturalGoods'] = city.updateCulturalGoods(cultBon / 50);
  4343. changes['priests'] = city.updatePriests(priests);
  4344. changes['research'] = city.updateResearchers(researchers);
  4345.  
  4346. events(Constant.Events.CITY_UPDATED).pub(ikariam.CurrentCityId, changes);
  4347. //parseInt(data.js_TownHallSatisfactionOverviewWineBoniServeBonusValue.text)/60
  4348. database.getGlobalData.addLocalisedString('Scientists', $('#js_TownHallPopulationGraphScientists').find('div.type img').attr('title'));
  4349. database.getGlobalData.addLocalisedString('Priests', $('#js_TownHallPopulationGraphPriests').find('div.type img').attr('title'));
  4350. database.getGlobalData.addLocalisedString('Citizens', $('#js_TownHallPopulationGraphCitizens').find('div.type img').attr('title'));
  4351. database.getGlobalData.addLocalisedString('Satisfaction', $('#townHall').find('div.contentBox01h h3.header').get(2).textContent);
  4352. },
  4353. parseTemple : function(data) {
  4354. var priests = parseInt(data['js_TempleSlider']['slider']['ini_value']) || 0;
  4355. var changed = ikariam.getCurrentCity.updatePriests(priests);
  4356. events(Constant.Events.CITY_UPDATED).pub(ikariam.CurrentCityId, {priests: changed})
  4357. },
  4358. parseMilitaryAdvisor : function(html, data) {
  4359. try {
  4360. var ownMovementIds = [];
  4361. var move;
  4362. for(var key in data) {
  4363. var match = key.match(/^js_MilitaryMovementsEventRow(\d+)$/);
  4364. if(match && Utils.existsIn(data[key]['class'], 'own')) {
  4365. ownMovementIds.push(match[1])
  4366. }
  4367. }
  4368. var changes = database.getGlobalData.clearFleetMovements();
  4369. if(ownMovementIds.length) {
  4370. $.each(ownMovementIds, function(idx, value) {
  4371. var transport = new Movement(value);
  4372. transport._id = parseInt(value);
  4373. transport._arrivalTime = parseInt(data['js_MilitaryMovementsEventRow' + value + 'ArrivalTime'].countdown.enddate * 1000);
  4374. transport._loadingTime = 0;
  4375. transport._originCityId = parseInt(data['js_MilitaryMovementsEventRow' + value + 'OriginLink'].href.match(/cityId=(\d+)/)[1]);
  4376. transport._targetCityId = parseInt(data['js_MilitaryMovementsEventRow' + value + 'TargetLink'].href.match(/cityId=(\d+)/)[1]);
  4377. transport._mission = data['js_MilitaryMovementsEventRow' + value + 'MissionIcon']['class'].split(' ')[1];
  4378. var status = data['js_MilitaryMovementsEventRow' + value + 'Mission']['class'];
  4379. if(status) {
  4380. if(Utils.existsIn(status, 'arrow_left_green')) {
  4381. var t = transport._originCityId;
  4382. transport._originCityId = transport._targetCityId;
  4383. transport._targetCityId = t;
  4384. }
  4385. } else {
  4386. transport._loadingTime = transport._arrivalTime;
  4387. if(database.getCityFromId(transport._originCityId) && database.getCityFromId(transport._targetCityId)) {
  4388. transport._arrivalTime += Utils.estimateTravelTime(database.getCityFromId(transport._originCityId).getCoordinates, database.getCityFromId(transport._targetCityId).getCoordinates);
  4389. }
  4390. }
  4391. switch(transport._mission) {
  4392. case 'trade':
  4393. case 'transport':
  4394. $.each(data['js_MilitaryMovementsEventRow' + value + 'UnitDetails']['appendElement'], function(index, item) {
  4395. if(Utils.existsIn(item['class'], Constant.Resources.WOOD)) {
  4396. transport._resources.wood = parseInt(item.text);
  4397. } else if(Utils.existsIn(item['class'], Constant.Resources.WINE)) {
  4398. transport._resources.wine = parseInt(item.text);
  4399. } else if(Utils.existsIn(item['class'], Constant.Resources.MARBLE)) {
  4400. transport._resources.marble = parseInt(item.text);
  4401. } else if(Utils.existsIn(item['class'], Constant.Resources.GLASS)) {
  4402. transport._resources.glass = parseInt(item.text);
  4403. } else if(Utils.existsIn(item['class'], Constant.Resources.SULFUR)) {
  4404. transport._resources.sulfur = parseInt(item.text);
  4405. }
  4406. });
  4407. break;
  4408. case 'deployarmy':
  4409. case 'deployfleet':
  4410. transport._military = new MilitaryUnits();
  4411. $.each(data['js_MilitaryMovementsEventRow' + value + 'UnitDetails'].appendElement, function(index, item) {
  4412. $.each(Constant.UnitData, function findIsUnit(val, info) {
  4413. if(Utils.existsIn(item['class'], ' ' + val)) {
  4414. transport._military.setUnit(val, parseInt(item.text));
  4415. return false;
  4416. }
  4417. });
  4418. });
  4419. break;
  4420. //TODO: other military movements
  4421. default:
  4422. return true
  4423. }
  4424. database.getGlobalData.addFleetMovement(transport);
  4425. changes.push(transport._targetCityId);
  4426. });
  4427. }
  4428. if(changes.length) events(Constant.Events.MOVEMENTS_UPDATED).pub($.exclusive(changes))
  4429. } catch(e) {
  4430. SITR.error('parseMilitaryAdvisor', e);
  4431. } finally {
  4432. }
  4433.  
  4434. },
  4435. parseCityMilitary : function() {
  4436. try {
  4437. var $elemArmy = $('#tabUnits').find('> div.contentBox01h td');
  4438. var $elemShips = $('#tabShips').find('> div.contentBox01h td');
  4439.  
  4440. var city = ikariam.getCurrentCity;
  4441. var cityArmy = {};
  4442.  
  4443. cityArmy[Constant.Military.SLINGER] = parseInt($elemArmy[4].innerHTML);
  4444. cityArmy[Constant.Military.SWORDSMAN] = parseInt($elemArmy[3].innerHTML);
  4445. cityArmy[Constant.Military.HOPLITE] = parseInt($elemArmy[0].innerHTML);
  4446. cityArmy[Constant.Military.MARKSMAN] = parseInt($elemArmy[6].innerHTML);
  4447. cityArmy[Constant.Military.MORTAR] = parseInt($elemArmy[9].innerHTML);
  4448. cityArmy[Constant.Military.CATAPULT] = parseInt($elemArmy[8].innerHTML);
  4449. cityArmy[Constant.Military.RAM] = parseInt($elemArmy[7].innerHTML);
  4450. cityArmy[Constant.Military.STEAM_GIANT] = parseInt($elemArmy[1].innerHTML);
  4451. cityArmy[Constant.Military.BALLOON_BOMBADIER] = parseInt($elemArmy[11].innerHTML);
  4452. cityArmy[Constant.Military.COOK] = parseInt($elemArmy[12].innerHTML);
  4453. cityArmy[Constant.Military.DOCTOR] = parseInt($elemArmy[13].innerHTML);
  4454. cityArmy[Constant.Military.GYROCOPTER] = parseInt($elemArmy[10].innerHTML);
  4455. cityArmy[Constant.Military.ARCHER] = parseInt($elemArmy[5].innerHTML);
  4456. cityArmy[Constant.Military.SPEARMAN] = parseInt($elemArmy[2].innerHTML);
  4457.  
  4458. cityArmy[Constant.Military.RAM_SHIP] = parseInt($elemShips[2].innerHTML);
  4459. cityArmy[Constant.Military.FLAME_THROWER] = parseInt($elemShips[0].innerHTML);
  4460. cityArmy[Constant.Military.SUBMARINE] = parseInt($elemShips[7].innerHTML);
  4461. cityArmy[Constant.Military.BALLISTA_SHIP] = parseInt($elemShips[4].innerHTML);
  4462. cityArmy[Constant.Military.CATAPULT_SHIP] = parseInt($elemShips[3].innerHTML);
  4463. cityArmy[Constant.Military.MORTAR_SHIP] = parseInt($elemShips[5].innerHTML);
  4464. cityArmy[Constant.Military.STEAM_RAM] = parseInt($elemShips[1].innerHTML);
  4465. cityArmy[Constant.Military.ROCKET_SHIP] = parseInt($elemShips[6].innerHTML);
  4466. cityArmy[Constant.Military.PADDLE_SPEEDBOAT] = parseInt($elemShips[8].innerHTML);
  4467. cityArmy[Constant.Military.BALLOON_CARRIER] = parseInt($elemShips[9].innerHTML);
  4468. cityArmy[Constant.Military.TENDER] = parseInt($elemShips[10].innerHTML);
  4469. var changes = city.military.updateUnits(cityArmy);
  4470. //events('dataUpdated').pub(ikariam.CurrentCityId, 'cityMilitary');
  4471. $elemArmy = null;
  4472. $elemShips = null;
  4473. events(Constant.Events.MILITARY_UPDATED).pub(city.getId, changes)
  4474.  
  4475. } catch(e) {
  4476. SITR.error('parseCityMilitary', e);
  4477. } finally {
  4478. }
  4479. },
  4480. parseMilitaryLocalization: function() {
  4481. var $elemA = $('#tabUnits').find('> div.contentBox01h th');
  4482. var $elemS = $('#tabShips').find('> div.contentBox01h th');
  4483. if(($elemA.length == 0) || ($elemS.length == 0)) {
  4484. return false;
  4485. }
  4486. database.getGlobalData.addLocalisedString('phalanx', $elemA[0].getAttribute('title'));
  4487. database.getGlobalData.addLocalisedString('steamgiant', $elemA[1].getAttribute('title'));
  4488. database.getGlobalData.addLocalisedString('spearman', $elemA[2].getAttribute('title'));
  4489. database.getGlobalData.addLocalisedString('swordsman', $elemA[3].getAttribute('title'));
  4490. database.getGlobalData.addLocalisedString('slinger', $elemA[4].getAttribute('title'));
  4491. database.getGlobalData.addLocalisedString('archer', $elemA[5].getAttribute('title'));
  4492. database.getGlobalData.addLocalisedString('marksman', $elemA[6].getAttribute('title'));
  4493. database.getGlobalData.addLocalisedString('ram', $elemA[7].getAttribute('title'));
  4494. database.getGlobalData.addLocalisedString('catapult', $elemA[8].getAttribute('title'));
  4495. database.getGlobalData.addLocalisedString('mortar', $elemA[9].getAttribute('title'));
  4496. database.getGlobalData.addLocalisedString('gyrocopter', $elemA[10].getAttribute('title'));
  4497. database.getGlobalData.addLocalisedString('bombardier', $elemA[11].getAttribute('title'));
  4498. database.getGlobalData.addLocalisedString('cook', $elemA[12].getAttribute('title'));
  4499. database.getGlobalData.addLocalisedString('medic', $elemA[13].getAttribute('title'));
  4500. database.getGlobalData.addLocalisedString('ship_ram', $elemS[2].getAttribute('title'));
  4501. database.getGlobalData.addLocalisedString('ship_flamethrower', $elemS[0].getAttribute('title'));
  4502. database.getGlobalData.addLocalisedString('ship_steamboat', $elemS[1].getAttribute('title'));
  4503. database.getGlobalData.addLocalisedString('ship_ballista', $elemS[4].getAttribute('title'));
  4504. database.getGlobalData.addLocalisedString('ship_catapult', $elemS[3].getAttribute('title'));
  4505. database.getGlobalData.addLocalisedString('ship_mortar', $elemS[5].getAttribute('title'));
  4506. database.getGlobalData.addLocalisedString('ship_submarine', $elemS[7].getAttribute('title'));
  4507. database.getGlobalData.addLocalisedString('ship_paddlespeedship', $elemS[8].getAttribute('title'));
  4508. database.getGlobalData.addLocalisedString('ship_ballooncarrier', $elemS[9].getAttribute('title'));
  4509. database.getGlobalData.addLocalisedString('ship_tender', $elemS[10].getAttribute('title'));
  4510. database.getGlobalData.addLocalisedString('ship_rocketship', $elemS[6].getAttribute('title'));
  4511. $elemA = null;
  4512. $elemS = null
  4513. },
  4514. parsePremium :function(view, html, tData){
  4515. var changes =[];
  4516. var features= [];
  4517. $('#premiumOffers').find('table.table01 tbody > tr[class]:not([class=""])')
  4518. .each(function(){
  4519. var item = $(this).attr('class').split(' ').shift();
  4520. if (Constant.PremiumData[item] !== undefined){
  4521. features.push(item)
  4522. }
  4523. });
  4524. $.each(features, function(index, val){
  4525. var active = false;
  4526. var endTime = 0;
  4527. var continuous = false;
  4528. var type = 0;
  4529. active = $('#js_buy'+val+'ActiveTime').hasClass('green');
  4530. if(active){
  4531. endTime = parseInt($('#js_buy'+val+'Link').attr('href').split('typeUntil=').pop().split('&').shift()) - Constant.PremiumData[val].duration;
  4532. if (isNaN(endTime)){
  4533. var str = $('#js_buy'+val+'ActiveTime').text();
  4534. var time = new Date();
  4535. time.setSeconds(time.getSeconds() + (str.match(/(\d+)s/) ? parseInt(str.match(/(\d+)s/)[1]) : 0));
  4536. time.setMinutes(time.getMinutes() + (str.match(/(\d+)m/) ? parseInt(str.match(/(\d+)m/)[1]) : 0));
  4537. time.setHours(time.getHours() + (str.match(/(\d+)h/) ? parseInt(str.match(/(\d+)h/)[1]) : 0));
  4538. time.setDate(time.getDate() + (str.match(/(\d+)D/) ? parseInt(str.match(/(\d+)D/)[1]) : 0));
  4539. endTime = time.getTime()/1000
  4540. }
  4541. type = parseInt($('#js_buy'+val+'Link').attr('href').split('type=').pop().split('&').shift());
  4542. continuous = $('#empireViewExtendCheckbox'+type+'Img').hasClass('checked');
  4543. }
  4544. changes.push(database.getGlobalData.setPremiumFeature(val,endTime*1000,continuous))
  4545. });
  4546. events(Constant.Events.PREMIUM_UPDATED).pub(changes);
  4547. },
  4548. FetchAllTowns : function() {
  4549. var _relatedCityData = unsafeWindow.ikariam.model.relatedCityData;
  4550. var _cityId = null;
  4551. var city = null;
  4552. var order = database.settings.cityOrder.value
  4553. if (!order.length) order = []; //temporary
  4554. if(_relatedCityData) {
  4555. for(_cityId in _relatedCityData) {
  4556. if(_cityId != 'selectedCity' && _cityId != 'additionalInfo') {
  4557. var own = (_relatedCityData[_cityId]['relationship'] == 'ownCity');
  4558. if(own) {
  4559. if(database.cities[_relatedCityData[_cityId]['id']] == undefined) {
  4560. (database.cities[_relatedCityData[_cityId]['id']] = database.addCity(_relatedCityData[_cityId]['id'])).init();
  4561. city = database.cities[_relatedCityData[_cityId]['id']];
  4562. city.updateTradeGoodID(parseInt(_relatedCityData[_cityId]['tradegood']));
  4563. city.isOwn = own;
  4564. }
  4565. city = database.cities[_relatedCityData[_cityId]['id']];
  4566. city.updateName(_relatedCityData[_cityId]['name']);
  4567. var coords = _relatedCityData[_cityId]['coords'].match(/(\d+)/);
  4568. city.updateCoordinates(coords[0], coords[1]);
  4569. if($.inArray(city.getId, order) == -1) {
  4570. order.push(city.getId);
  4571. }
  4572. }
  4573. }
  4574. }
  4575. //remove deleted cities
  4576. for(var cID in database.cities) {
  4577. var ghost = true;
  4578. for(_cityId in _relatedCityData) {
  4579. if(_relatedCityData[_cityId]['id'] == cID || !database.cities[cID].isOwn) {
  4580. ghost = false;
  4581. }
  4582. }
  4583. if(ghost) {
  4584. delete database.cities[cID]
  4585. }
  4586. }
  4587. }
  4588. database.settings.cityOrder.value = order;
  4589. },
  4590. get currentShips() {
  4591. if(this.$freeTransporters == undefined) {
  4592. this.$freeTransporters = $('#js_GlobalMenu_freeTransporters');
  4593. }
  4594. return parseInt(this.$freeTransporters.text())
  4595. }
  4596. };
  4597.  
  4598. /***********************************************************************************************************************
  4599. * Constants
  4600. **********************************************************************************************************************/
  4601. var Constant = {
  4602. PremiumData:{
  4603. PremiumAccount:{
  4604. type:15,
  4605. duration:7 * 24 * 60,
  4606. cost:0,
  4607. bonus:0,
  4608. icon:''
  4609. },
  4610. ResourceBonus:{
  4611. type:16,
  4612. duration:7 * 24 * 60,
  4613. cost:0,
  4614. bonus:0.2,
  4615. icon:''
  4616. },
  4617. WineBonus:{
  4618. type:14,
  4619. duration:7 * 24 * 60,
  4620. cost:0,
  4621. bonus:0.2,
  4622. icon:''
  4623. },
  4624. MarbleBonus:{
  4625. type:11,
  4626. duration:7 * 24 * 60,
  4627. cost:0,
  4628. bonus:0.2,
  4629. icon:''
  4630. },
  4631. SulfurBonus:{
  4632. type:12,
  4633. duration:7 * 24 * 60,
  4634. cost:0,
  4635. bonus:0.2,
  4636. icon:''
  4637. },
  4638. CrystalBonus:{
  4639. type:13,
  4640. duration:7 * 24 * 60,
  4641. cost:0,
  4642. bonus:0.2,
  4643. icon:''
  4644. },
  4645. ResearchPointsBonus:{
  4646. type:18,
  4647. duration:7 * 24 * 60,
  4648. cost:0,
  4649. bonus:0.2,
  4650. icon:'skin/premium/b_premium_research.jpg'
  4651. },
  4652. ResearchPointsBonusExtremeLength:{
  4653. type:0,
  4654. duration:70 * 24 * 60,
  4655. cost:0,
  4656. bonus:0.2,
  4657. icon:'skin/premium/b_premium_research_big.jpg'
  4658. },
  4659. SafecapacityBonus:{
  4660. type:17,
  4661. duration:7 * 24 * 60,
  4662. cost:0,
  4663. bonus:1,
  4664. icon:'skin/premium/b_premium_safecapacity.jpg'
  4665. },
  4666. StoragecapacityBonus:{
  4667. type:33,
  4668. duration:7 * 24 * 60,
  4669. cost:0,
  4670. bonus:1,
  4671. icon:'skin/premium/b_premium_storagecapacity.jpg'
  4672. }
  4673. },
  4674. Premium:{
  4675. PREMIUM_ACCOUNT:'PremiumAccount',
  4676. RESOURCE_BONUS:'ResourceBonus',
  4677. WINE_BONUS:'WineBonus',
  4678. MARBLE_BONUS:'MarbleBonus',
  4679. SULFUR_BONUS:'SulfurBonus',
  4680. CRYSTAL_BONUS:'CrystalBonus',
  4681. RESEARCH_POINTS_BONUS:'ResearchPointsBonus',
  4682. RESEARCH_POINTS_BONUS_EXTREME_LENGTH:'ResearchPointsBonusExtremeLength',
  4683. SAFECAPACITY_BONUS:'SafecapacityBonus',
  4684. STORAGECAPACITY_BONUS:'StoragecapacityBonus',
  4685. },
  4686. Events : {
  4687. BUILDINGS_UPDATED: 'buildingsUpdated',
  4688. GLOBAL_UPDATED : 'globalDataUpdated',
  4689. MOVEMENTS_UPDATED: 'movementsUpdated',
  4690. RESOURCES_UPDATED: 'resourcesUpdated',
  4691. CITY_UPDATED : 'cityData',
  4692. MILITARY_UPDATED : 'militaryUpdated',
  4693. LOCAL_STRINGS_AVAILABLE : 'localisationAvailable',
  4694. MODEL_AVAILABLE : 'modelAvailable',
  4695. CITYDATA_AVAILABLE: 'cityDataAvailable',
  4696. DATABASE_LOADED: 'databaseLoaded',
  4697. TAB_CHANGED : 'tabChanged',
  4698. PREMIUM_UPDATED : 'premiumUpdated',
  4699. },
  4700. Settings: {
  4701. CITY_ORDER: 'cityOrder',
  4702. FULL_ARMY_TABLE: 'fullArmyTable',
  4703. HIDE_ISLAND: 'hideOnIslandView',
  4704. HIDE_WORLD: 'hideOnWorldView',
  4705. HIDE_CITY: 'hideOnCityView',
  4706. SHOW_ON_TOP: 'onTop',
  4707. WINDOW_TENNIS: 'windowTennis',
  4708. AUTO_UPDATE: 'autoUpdates',
  4709. SMALLER_FONT: 'smallFont',
  4710. COMPRESS_BUILDINGS: 'compressedBuildingList',
  4711. WINE_WARNING_TIME: 'wineWarningTime',
  4712. },
  4713. SettingData:{
  4714. cityOrder:{type:'array', default:[], category:'ignore'},
  4715. fullArmyTable:{type:'boolean', default:false, category:'army_category'},
  4716. hideOnIslandView:{type:'boolean', default:false, category:'visibility_category'},
  4717. hideOnWorldView:{type:'boolean', default:false, category:'visibility_category'},
  4718. hideOnCityView:{type:'boolean', default:false, category:'visibility_category'},
  4719. onTop:{type:'boolean', default:true, category:'display_category'},
  4720. windowTennis:{type:'boolean', default:false, category:'display_category'},
  4721. autoUpdates:{type:'boolean', default:true, category:'global_category'},
  4722. smallFont:{type:'boolean', default:false, category:'display_category'},
  4723. compressedBuildingList:{type:'boolean', default:false, category:'building_category'},
  4724. wineWarningTime:{type:'number', default:24, choices:[12,24,36,48], category:'resource_category'}
  4725. },
  4726. SettingCategories: {
  4727. VISIBILITY: 'visibility_category',
  4728. DISPLAY : 'display_category',
  4729. OTHER : 'global_category',
  4730. ARMY : 'army_category',
  4731. BUILDING : 'building_category',
  4732. RESOURCE : 'resource_category',
  4733. },
  4734. Localization : {
  4735. default : {
  4736. //settings
  4737. cityOrder : 'cityOrder',
  4738. fullArmyTable : 'Show All Military Units',
  4739. hideOnIslandView : 'Force hide on island view',
  4740. hideOnWorldView : 'Force hide on world view',
  4741. hideOnCityView : 'Force hide on city view (NYI)',
  4742. onTop : 'Show on top of Ikariam windows',
  4743. windowTennis : 'Show above ikariam on mouseover',
  4744. autoUpdates : 'Automaticly check for updates',
  4745. smallFont : 'Use smaller font size',
  4746. compressedBuildingList : 'Use compressed building list',
  4747. wineWarningTime : 'Wine remaining warning',
  4748. //settings descriptions
  4749. cityOrder_description : 'cityOrder_description',
  4750. fullArmyTable_description : 'Show all possible army units on the Army tab',
  4751. hideOnIslandView_description : 'Hide by default on world view',
  4752. hideOnWorldView_description : 'Hide by default on island view',
  4753. hideOnCityView_description : 'Hide by default on city view',
  4754. onTop_description : 'Show board on top of Ikariam windows',
  4755. windowTennis_description : 'Bring board to the top on mouseover<br>Send behind ikariam windows on mouseout<br>Ignores \'on top\' option',
  4756. autoUpdates_description : 'Enable automatic update checking<br>(Once every 24hrs)',
  4757. smallFont_description : 'Use a smaller font for the data tables',
  4758. compressedBuildingList_description : 'Use condensed building table<br>Groups luxury resource production buildings<br>Groups palace/govenors residence',
  4759. wineWarningTime_description : 'Wine remaining time turns \'red\' at this point',
  4760. // settings categories
  4761. visibility_category : 'Board Visibility',
  4762. display_category : 'Display Settings',
  4763. global_category : 'Global Settings',
  4764. army_category : 'Army Settings',
  4765. building_category : 'Building Settings',
  4766. resource_category : 'Resource Settings',
  4767. // formatting
  4768. thousandSeperator : ',',
  4769. decimalPoint:'.',
  4770. click:'click'
  4771. }
  4772. },
  4773. Resources : {
  4774. WOOD : 'wood',
  4775. WINE : 'wine',
  4776. MARBLE: 'marble',
  4777. GLASS : 'glass',
  4778. SULFUR: 'sulfur'
  4779. },
  4780. ResourceIDs : {
  4781. WOOD : 'resource',
  4782. WINE : 1,
  4783. MARBLE: 2,
  4784. GLASS : 3,
  4785. SULFUR: 4
  4786. },
  4787. Research : {
  4788. Seafaring: {
  4789. CARPENTRY : 2150,
  4790. DECK_WEAPONS : 1010,
  4791. PIRACY : 1170,
  4792. SHIP_MAINTENANCE : 1020,
  4793. DRAFT : 1130,
  4794. EXPANSION : 1030,
  4795. FOREIGN_CULTURES : 1040,
  4796. PITCH : 1050,
  4797. MARKET : 2070,
  4798. GREEK_FIRE : 1060,
  4799. COUNTERWEIGHT : 1070,
  4800. DIPLOMACY : 1080,
  4801. SEA_MAPS : 1090,
  4802. PADDLE_WHEEL_ENGINE: 1100,
  4803. CAULKING : 1140,
  4804. MORTAR_ATTACHMENT : 1110,
  4805. MASSIVE_RAM : 1150,
  4806. OFFSHORE_BASE : 1160,
  4807. SEAFARING_FUTURE : 1999
  4808. },
  4809. Economy : {
  4810. CONSERVATION : 2010,
  4811. PULLEY : 2020,
  4812. WEALTH : 2030,
  4813. WINE_CULTURE : 2040,
  4814. IMPROVED_RESOURCE_GATHERING: 2130,
  4815. GEOMETRY : 2060,
  4816. ARCHITECTURE : 1120,
  4817. HOLIDAY : 2080,
  4818. LEGISLATION : 2170,
  4819. CULINARY_SPECIALITIES : 2050,
  4820. HELPING_HANDS : 2090,
  4821. SPIRIT_LEVEL : 2100,
  4822. WINE_PRESS : 2140,
  4823. DEPOT : 2160,
  4824. BUREACRACY : 2110,
  4825. UTOPIA : 2120,
  4826. ECONOMIC_FUTURE : 2999
  4827. },
  4828. Science : {
  4829. WELL_CONSTRUCTION : 3010,
  4830. PAPER : 3020,
  4831. ESPIONAGE : 3030,
  4832. POLYTHEISM : 3040,
  4833. INK : 3050,
  4834. GOVERNMENT_FORMATION : 3150,
  4835. INVENTION : 3140,
  4836. CULTURAL_EXCHANGE : 3060,
  4837. ANATOMY : 3070,
  4838. OPTICS : 3080,
  4839. EXPERIMENTS : 3081,
  4840. MECHANICAL_PEN : 3090,
  4841. BIRDS_FLIGHT : 3100,
  4842. LETTER_CHUTE : 3110,
  4843. STATE_RELIGION : 3160,
  4844. PRESSURE_CHAMBER : 3120,
  4845. ARCHIMEDEAN_PRINCIPLE: 3130,
  4846. SCIENTIFIC_FUTURE : 3999
  4847. },
  4848. Military : {
  4849. DRY_DOCKS : 4010,
  4850. MAPS : 4020,
  4851. PROFESSIONAL_ARMY : 4030,
  4852. SEIGE : 4040,
  4853. CODE_OF_HONOR : 4050,
  4854. BALLISTICS : 4060,
  4855. LAW_OF_THE_LEVEL : 4070,
  4856. GOVERNOR : 4080,
  4857. PYROTECHNICS : 4130,
  4858. LOGISTICS : 4090,
  4859. GUNPOWDER : 4100,
  4860. ROBOTICS : 4110,
  4861. CANNON_CASTING : 4120,
  4862. MILITARISTIC_FUTURE: 4999
  4863. }
  4864. },
  4865. Military : {
  4866. // Army
  4867. HOPLITE : 'phalanx',
  4868. STEAM_GIANT : 'steamgiant',
  4869. SPEARMAN : 'spearman',
  4870. SWORDSMAN : 'swordsman',
  4871. SLINGER : 'slinger',
  4872. ARCHER : 'archer',
  4873. MARKSMAN : 'marksman',
  4874. RAM : 'ram',
  4875. CATAPULT : 'catapult',
  4876. MORTAR : 'mortar',
  4877. GYROCOPTER : 'gyrocopter',
  4878. BALLOON_BOMBADIER: 'bombardier',
  4879. COOK : 'cook',
  4880. DOCTOR : 'medic',
  4881. ARMY : 'army',
  4882.  
  4883. // Navy
  4884. RAM_SHIP : 'ship_ram',
  4885. FLAME_THROWER : 'ship_flamethrower',
  4886. STEAM_RAM : 'ship_steamboat',
  4887. BALLISTA_SHIP : 'ship_ballista',
  4888. CATAPULT_SHIP : 'ship_catapult',
  4889. MORTAR_SHIP : 'ship_mortar',
  4890. SUBMARINE : 'ship_submarine',
  4891. PADDLE_SPEEDBOAT : 'ship_paddlespeedship',
  4892. BALLOON_CARRIER : 'ship_ballooncarrier',
  4893. TENDER : 'ship_tender',
  4894. ROCKET_SHIP : 'ship_rocketship',
  4895. NAVY : 'navy'
  4896. },
  4897. unitIds : {
  4898. 301: 'slinger',
  4899. 302: 'swordsman',
  4900. 303: 'phalanx',
  4901. 304: 'marksman',
  4902. 305: 'mortar',
  4903. 306: 'catapult',
  4904. 307: 'ram',
  4905. 308: 'steamgiant',
  4906. 309: 'bombardier',
  4907. 310: 'cook',
  4908. 311: 'medic',
  4909. 312: 'gyrocopter',
  4910. 313: 'archer',
  4911. 315: 'spearman',
  4912. 316: 'barbarian',
  4913.  
  4914. 210: 'ship_ram',
  4915. 211: 'ship_flamethrower',
  4916. 212: 'ship_submarine',
  4917. 213: 'ship_ballista',
  4918. 214: 'ship_catapult',
  4919. 215: 'ship_mortar',
  4920. 216: 'ship_steamboat',
  4921. 217: 'ship_rocketship',
  4922. 218: 'ship_paddlespeedship',
  4923. 219: 'ship_ballooncarrier',
  4924. 220: 'ship_tender'
  4925. },
  4926. UnitData : {
  4927. slinger : {id: 301, type: 'army', position: 'army_ranged', minlevel: 2, baseTime: 90},
  4928. swordsman : {id: 302, type: 'army', position: 'army_flank', minlevel: 6, baseTime: 180},
  4929. phalanx : {id: 303, type: 'army', position: 'army_front_line', minlevel: 4, baseTime: 300},
  4930. marksman : {id: 304, type: 'army', position: 'army_ranged', minlevel: 13, baseTime: 600},
  4931. mortar : {id: 305, type: 'army', position: 'army_seige', minlevel: 14, baseTime: 2400},
  4932. catapult : {id: 306, type: 'army', position: 'army_seige', minlevel: 8, baseTime: 1800},
  4933. ram : {id: 307, type: 'army', position: 'army_seige', minlevel: 2, baseTime: 600},
  4934. steamgiant : {id: 308, type: 'army', position: 'army_front_line', minlevel: 12, baseTime: 900},
  4935. bombardier : {id: 309, type: 'army', position: 'army_air', minlevel: 11, baseTime: 1800},
  4936. cook : {id: 310, type: 'army', position: 'army_support', minlevel: 5, baseTime: 1200},
  4937. medic : {id: 311, type: 'army', position: 'army_support', minlevel: 9, baseTime: 1200},
  4938. gyrocopter : {id: 312, type: 'army', position: 'army_air', minlevel: 10, baseTime: 900},
  4939. archer : {id: 313, type: 'army', position: 'army_ranged', minlevel: 7, baseTime: 240},
  4940. spearman : {id: 315, type: 'army', position: 'army_flank', minLevel: 1, baseTime: 60},
  4941. ship_ram : {id: 210, type: 'fleet', position: 'navy_flank', minlevel: 1, baseTime: 2400},
  4942. ship_flamethrower : {id: 211, type: 'fleet', position: 'navy_front_line', minlevel: 4, baseTime: 1800},
  4943. ship_submarine : {id: 212, type: 'fleet', position: 'navy_seige', minlevel: 19, baseTime: 3600},
  4944. ship_ballista : {id: 213, type: 'fleet', position: 'navy_ranged', minlevel: 3, baseTime: 3000},
  4945. ship_catapult : {id: 214, type: 'fleet', position: 'navy_ranged', minlevel: 3, baseTime: 3000},
  4946. ship_mortar : {id: 215, type: 'fleet', position: 'navy_ranged', minlevel: 17, baseTime: 3000},
  4947. ship_steamboat : {id: 216, type: 'fleet', position: 'navy_front_line', minlevel: 15, baseTime: 2400},
  4948. ship_rocketship : {id: 217, type: 'fleet', position: 'navy_seige', minlevel: 11, baseTime: 3600},
  4949. ship_paddlespeedship: {id: 218, type: 'fleet', position: 'navy_air', minlevel: 13, baseTime: 1800},
  4950. ship_ballooncarrier : {id: 219, type: 'fleet', position: 'navy_air', minlevel: 7, baseTime: 3900},
  4951. ship_tender : {id: 220, type: 'fleet', position: 'navy_support', minlevel: 9, baseTime: 2400}
  4952. },
  4953. Government : {
  4954. ANARCHY : 'anarchie',
  4955. IKACRACY : 'ikakratie',
  4956. ARISTOCRACY : 'aristokratie',
  4957. DICTATORSHIP: 'diktatur',
  4958. DEMOCRACY : 'demokratie',
  4959. NOMOCRACY : 'nomokratie',
  4960. OLIGARCHY : 'oligarchie',
  4961. TECHNOCRACY : 'technokratie',
  4962. THEOCRACY : 'theokratie'
  4963. },
  4964. Buildings : {
  4965. TOWN_HALL : 'townHall',
  4966. PALACE : 'palace',
  4967. GOVERNORS_RESIDENCE: 'palaceColony',
  4968. TAVERN : 'tavern',
  4969. MUSEUM : 'museum',
  4970. ACADEMY : 'academy',
  4971. WORKSHOP : 'workshop',
  4972. TEMPLE : 'temple',
  4973. EMBASSY : 'embassy',
  4974. WAREHOUSE : 'warehouse',
  4975. DUMP : 'dump',
  4976. TRADING_PORT : 'port',
  4977. TRADING_POST : 'branchOffice',
  4978. WALL : 'wall',
  4979. HIDEOUT : 'safehouse',
  4980. BARRACKS : 'barracks',
  4981. SHIPYARD : 'shipyard',
  4982. FORESTER : 'forester',
  4983. CARPENTER : 'carpentering',
  4984. WINERY : 'winegrower',
  4985. VINEYARD : 'vineyard',
  4986. STONEMASON : 'stonemason',
  4987. ARCHITECT : 'architect',
  4988. GLASSBLOWER : 'glassblowing',
  4989. OPTICIAN : 'optician',
  4990. ALCHEMISTS_TOWER : 'alchemist',
  4991. FIREWORK_TEST_AREA : 'fireworker',
  4992. PIRATE_FORTRESS : 'pirateFortress',
  4993. BLACKMARKET : 'blackMarket',
  4994. MARINECHARTARCHIVE : 'marineChartArchive'
  4995. },
  4996. GovernmentData:{
  4997. anarchie:{
  4998. corruption:0.25,
  4999. spyprotection:0,
  5000. unitBuildTime:0,
  5001. fleetBuildTime:0,
  5002. loadingSpeed:0,
  5003. buildingTime:0,
  5004. happiness:0,
  5005. bonusShips:0,
  5006. armySupply:0,
  5007. fleetSupply:0,
  5008. researchPerCulturalGood:0,
  5009. tradeShipSpeed:0,
  5010. branchOfficeRange:0,
  5011. researchBonus:0,
  5012. researcherCost:0,
  5013. productivity:0,
  5014. happinessWithoutTemple:0,
  5015. goldBonusPerPriest:0,
  5016. cooldownTime:0,
  5017. happinessBonusWithTempleConversion:0
  5018. },
  5019. ikakratie:{
  5020. corruption:0,
  5021. spyprotection:0,
  5022. unitBuildTime:0,
  5023. fleetBuildTime:0,
  5024. loadingSpeed:0,
  5025. buildingTime:0,
  5026. happiness:0,
  5027. bonusShips:0,
  5028. armySupply:0,
  5029. fleetSupply:0,
  5030. researchPerCulturalGood:0,
  5031. tradeShipSpeed:0,
  5032. branchOfficeRange:0,
  5033. researchBonus:0,
  5034. researcherCost:0,
  5035. productivity:0,
  5036. happinessWithoutTemple:0,
  5037. goldBonusPerPriest:0,
  5038. cooldownTime:0,
  5039. happinessBonusWithTempleConversion:0
  5040. },
  5041. aristokratie:{
  5042. corruption:0.03,
  5043. spyprotection:0.2,
  5044. unitBuildTime:0,
  5045. fleetBuildTime:0,
  5046. loadingSpeed:0,
  5047. buildingTime:-0.2,
  5048. happiness:0,
  5049. bonusShips:0,
  5050. armySupply:0,
  5051. fleetSupply:0,
  5052. researchPerCulturalGood:0,
  5053. tradeShipSpeed:0,
  5054. branchOfficeRange:0,
  5055. researchBonus:0,
  5056. researcherCost:0,
  5057. productivity:0,
  5058. happinessWithoutTemple:0,
  5059. goldBonusPerPriest:0,
  5060. cooldownTime:0,
  5061. happinessBonusWithTempleConversion:0
  5062. },
  5063. diktatur:{
  5064. corruption:0,
  5065. spyprotection:0,
  5066. unitBuildTime:-0.02,
  5067. fleetBuildTime:-0.02,
  5068. loadingSpeed:0,
  5069. buildingTime:0,
  5070. happiness:-75,
  5071. bonusShips:2,
  5072. armySupply:-0.02,
  5073. fleetSupply:-0.02,
  5074. researchPerCulturalGood:0,
  5075. tradeShipSpeed:0,
  5076. branchOfficeRange:0,
  5077. researchBonus:0,
  5078. researcherCost:0,
  5079. productivity:0,
  5080. happinessWithoutTemple:0,
  5081. goldBonusPerPriest:0,
  5082. cooldownTime:0,
  5083. happinessBonusWithTempleConversion:0
  5084. },
  5085. demokratie:{
  5086. corruption:0,
  5087. spyprotection:-0.2,
  5088. unitBuildTime:0.05,
  5089. fleetBuildTime:0,
  5090. loadingSpeed:0,
  5091. buildingTime:0,
  5092. happiness:75,
  5093. bonusShips:0,
  5094. armySupply:0,
  5095. fleetSupply:0,
  5096. researchPerCulturalGood:1,
  5097. tradeShipSpeed:0,
  5098. branchOfficeRange:0,
  5099. researchBonus:0,
  5100. researcherCost:0,
  5101. productivity:0,
  5102. happinessWithoutTemple:0,
  5103. goldBonusPerPriest:0,
  5104. cooldownTime:0,
  5105. happinessBonusWithTempleConversion:0
  5106. },
  5107. nomokratie:{
  5108. corruption:-0.05,
  5109. spyprotection:0.2,
  5110. unitBuildTime:0.05,
  5111. fleetBuildTime:0.05,
  5112. loadingSpeed:0.5,
  5113. buildingTime:0,
  5114. happiness:0,
  5115. bonusShips:0,
  5116. armySupply:0,
  5117. fleetSupply:0,
  5118. researchPerCulturalGood:0,
  5119. tradeShipSpeed:0,
  5120. branchOfficeRange:0,
  5121. researchBonus:0,
  5122. researcherCost:0,
  5123. productivity:0,
  5124. happinessWithoutTemple:0,
  5125. goldBonusPerPriest:0,
  5126. cooldownTime:0,
  5127. happinessBonusWithTempleConversion:0
  5128. },
  5129. oligarchie:{
  5130. corruption:0.03,
  5131. spyprotection:0,
  5132. unitBuildTime:0,
  5133. fleetBuildTime:0,
  5134. loadingSpeed:0,
  5135. buildingTime:0.2,
  5136. happiness:0,
  5137. bonusShips:2,
  5138. armySupply:0,
  5139. fleetSupply:-0.02,
  5140. researchPerCulturalGood:0,
  5141. tradeShipSpeed:0.1,
  5142. branchOfficeRange:5,
  5143. researchBonus:0,
  5144. researcherCost:0,
  5145. productivity:0,
  5146. happinessWithoutTemple:0,
  5147. goldBonusPerPriest:0,
  5148. cooldownTime:0,
  5149. happinessBonusWithTempleConversion:0
  5150. },
  5151. technokratie:{
  5152. corruption:0,
  5153. spyprotection:0,
  5154. unitBuildTime:0,
  5155. fleetBuildTime:0,
  5156. loadingSpeed:0,
  5157. buildingTime:0,
  5158. happiness:0,
  5159. bonusShips:0,
  5160. armySupply:0,
  5161. fleetSupply:0,
  5162. researchPerCulturalGood:0,
  5163. tradeShipSpeed:0,
  5164. branchOfficeRange:0,
  5165. researchBonus:0.05,
  5166. researcherCost:1,
  5167. productivity:0.2,
  5168. happinessWithoutTemple:0,
  5169. goldBonusPerPriest:0,
  5170. cooldownTime:0,
  5171. happinessBonusWithTempleConversion:0
  5172. },
  5173. theokratie:{
  5174. corruption:0,
  5175. spyprotection:0,
  5176. unitBuildTime:0,
  5177. fleetBuildTime:0,
  5178. loadingSpeed:0,
  5179. buildingTime:0,
  5180. happiness:0,
  5181. bonusShips:0,
  5182. armySupply:0,
  5183. fleetSupply:0,
  5184. researchPerCulturalGood:0,
  5185. tradeShipSpeed:0,
  5186. branchOfficeRange:0,
  5187. researchBonus:-0.05,
  5188. researcherCost:0,
  5189. productivity:0,
  5190. happinessWithoutTemple:-20,
  5191. goldBonusPerPriest:1,
  5192. cooldownTime:-0.2,
  5193. happinessBonusWithTempleConversion:2
  5194. }
  5195. },
  5196. BuildingData:{
  5197. academy:{
  5198. buildingId:4,
  5199. maxLevel:32,
  5200. wood:[64, 68, 115, 263, 382, 626, 982, 1330, 2004, 2665, 3916, 5156, 7446, 9753, 12751, 18163, 23691, 33451, 43572, 56729, 73833, 103459, 144203, 175058, 243930, 317208, 439968, 536310, 743789, 1027470, 1257246, 1736683],
  5201. glass:[0, 0, 0, 0, 225, 428, 744, 1089, 1748, 2454, 3786, 5216, 7862, 10729, 14599, 21627, 29322, 43020, 58213, 78724, 106414, 154857, 224146, 282572, 408877, 552141, 795252, 1006648, 1449741, 2079651, 2642548, 3790583],
  5202. marble:0,
  5203. sulfur:0,
  5204. wine:0,
  5205. time:{a:1440, b:1, c:1.2, d:720},
  5206. icon:'skin/img/city/academy_l.png',
  5207. maxScientists:[0, 8, 12, 16, 22, 28, 35, 43, 51, 60, 69, 79, 89, 100, 111, 122, 134, 146, 159, 172, 185, 198, 212, 227, 241, 256, 271, 287, 302, 318, 335, 351, 368 ]
  5208. },
  5209. alchemist:{
  5210. buildingId:22,
  5211. maxLevel:32,
  5212. wood:[274, 467, 718, 1045, 1469, 2021, 2738, 3671, 4883, 6459, 8508, 11172, 14634, 19135, 24987, 32594, 42483, 55339, 72051, 93778, 122022, 158740, 206472, 268525, 349194, 454063, 590393, 767619, 998019, 1297536, 1686907, 2193090],
  5213. glass:0,
  5214. marble:[0, 116, 255, 436, 671, 977, 1375, 1892, 2564, 3437, 4572, 6049, 7968, 10462, 13705, 17921, 23402, 30527, 39790, 51831, 67485, 87835, 114290, 148681, 193390, 251512, 327069, 425295, 552987, 718988, 934789, 1215330],
  5215. sulfur:0,
  5216. wine:0,
  5217. time:{a:72000, b:11, c:1.1, d:6120},
  5218. icon:'skin/img/city/alchemist_l.png'
  5219. },
  5220. architect:{
  5221. buildingId:24,
  5222. maxLevel:32,
  5223. wood:[185, 291, 413, 555, 720, 911, 1133, 1390, 1689, 2035, 2437, 2902, 3443, 4070, 4797, 5640, 6619, 7754, 9070, 10598, 12369, 14424, 16808, 19573, 22781, 26502, 30818, 35825, 41633, 48371, 56186, 65252],
  5224. glass:0,
  5225. marble:[106, 160, 222, 295, 379, 475, 587, 716, 865, 1036, 1233, 1460, 1722, 2023, 2369, 2767, 3226, 3753, 4359, 5056, 5857, 6778, 7836, 9052, 10449, 12055, 13899, 16017, 18451, 21246, 24455, 28141],
  5226. sulfur:0,
  5227. wine:0,
  5228. time:{a:125660, b:37, c:1.06, d:2628},
  5229. icon:'skin/img/city/architect_l.png'
  5230. },
  5231. barracks:{
  5232. buildingId:6,
  5233. maxLevel:54,
  5234. wood:[49, 114, 195, 296, 420, 574, 766, 1003, 1297, 1662, 2115, 2676, 3371, 4234, 5304, 6630, 8275, 10314, 12843, 15979, 19868, 24690, 30669, 38083, 47277, 58676, 72812, 90341, 112076, 139028, 172448, 213889, 265276, 328996, 408008, 505984, 627473, 778120, 964923, 1196558, 1483785, 1839947, 2281558, 2829223, 3508290, 4350333, 5394466, 6689191, 8294651, 10285421, 12753975, 15814983, 19610632, 24317237],
  5235. glass:0,
  5236. marble:[0, 0, 0, 0, 0, 0, 0, 0, 178, 431, 745, 1134, 1616, 2214, 2956, 3875, 5015, 6429, 8183, 10357, 13052, 16395, 20540, 25680, 32054, 39957, 49757, 61909, 76977, 95661, 118830, 147560, 183185, 227359, 282136, 350059, 434283, 538721, 668224, 828808, 1027932, 1274847, 1581020, 1960675, 2431447, 3015205, 3739064, 4636650, 5749656, 7129784, 8841142, 10963226, 13594611, 16857527],
  5237. sulfur:0,
  5238. wine:0,
  5239. time:{a:25200, b:11, c:1.1, d:1728},
  5240. icon:'skin/img/city/barracks_l.png'
  5241. },
  5242. branchOffice:{
  5243. buildingId:13,
  5244. maxLevel:32,
  5245. wood:[48, 173, 346, 581, 896, 1314, 1863, 2580, 3509, 4706, 6241, 8203, 10699, 13866, 17872, 22926, 29286, 37273, 47283, 59807, 75448, 94955, 119245, 149454, 186977, 233530, 291226, 362658, 451015, 560208, 695038, 861391],
  5246. glass:0,
  5247. marble:[0, 0, 0, 0, 540, 792, 1123, 1555, 2115, 2837, 3762, 4945, 6450, 8359, 10774, 13820, 17654, 22469, 28503, 36051, 45482, 57240, 71883, 90092, 112712, 121067, 175556, 218617, 271878, 337705, 418983, 446564],
  5248. sulfur:0,
  5249. wine:0,
  5250. time:{a:108000, b:11, c:1.1, d:9360},
  5251. icon:'skin/img/city/branchoffice_l.png'
  5252. },
  5253. carpentering:{
  5254. buildingId:23,
  5255. maxLevel:32,
  5256. wood:[63, 122, 192, 274, 372, 486, 620, 777, 962, 1178, 1432, 1730, 2078, 2486, 2964, 3524, 4178, 4945, 5841, 6890, 8117, 95501, 11229, 13190, 15484, 18165, 21299, 24963, 29245, 34249, 40096, 46930],
  5257. glass:0,
  5258. marble:[0, 0, 0, 0, 0, 0, 0, 359, 444, 546, 669, 816, 993, 1205, 1459, 1765, 2131, 2571, 3098, 3731, 4491, 5402, 6496, 7809, 9384, 11275, 13543, 16265, 19531, 23451, 28154, 33799],
  5259. sulfur:0,
  5260. wine:0,
  5261. time:{a:125660, b:37, c:1.06, d:2808},
  5262. icon:'skin/img/city/carpentering_l.png'
  5263. },
  5264. dump:{
  5265. buildingId:29,
  5266. maxLevel:40,
  5267. wood:[640, 1152, 1766, 2504, 3388, 4450, 5724, 7253, 9088, 11289, 13931, 17101, 20905, 25470, 30948, 37522, 45410, 54876, 66236, 79867, 96224, 115853, 139408, 167673, 201592, 242294, 291137, 349749, 420082, 504483, 605763, 727300, 873144, 1048157, 1258172, 1510191, 1812613, 2175519, 2611007, 3133593],
  5268. glass:[701, 1146, 1668, 2278, 2991, 3526, 4803, 5946, 7283, 8847, 10678, 12819, 15325, 18257, 21687, 25700, 30395, 35889, 42316, 49837, 58635, 68930, 80974, 95066, 111554, 130844, 153414, 179821, 201717, 246865, 289158, 338642, 396537, 464275, 543528, 636254, 744743, 871676, 1020188, 1193946],
  5269. marble:[497, 932, 1445, 2051, 2762, 3609, 4604, 5778, 7164, 8799, 10728, 13005, 15691, 18862, 22602, 27016, 32225, 38371, 45623, 54181, 64279, 76195, 90256, 106847, 126425, 149528, 176788, 208956, 246913, 291703, 344555, 406921, 480512, 567350, 669818, 790731, 933409, 1101768, 1300432, 1534855],
  5270. sulfur:[384, 845, 1398, 2061, 2858, 3813, 4960, 6336, 7987, 9968, 12346, 15199, 18623, 22731, 27661, 33578, 40677, 49197, 59420, 71688, 86410, 104076, 125275, 150714, 181241, 217873, 261831, 314582, 377882, 453843, 544995, 654378, 785638, 943149, 1132163, 1358980, 1631160, 1957775, 2349715, 2820041],
  5271. wine:0,
  5272. time:{a:32000, b:13, c:1.17, d:2160},
  5273. icon:'skin/img/city/dump_l.png'
  5274. },
  5275. embassy:{
  5276. buildingId:12,
  5277. maxLevel:32,
  5278. wood:[242, 415, 623, 873, 1173, 1532, 1964, 2482, 3103, 3849, 4743, 5817, 7105, 8651, 10507, 12733, 15404, 18610, 22457, 27074, 32614, 39261, 47239, 56811, 68299, 82084, 98625, 118475, 142295, 170879, 205180, 246341],
  5279. glass:0,
  5280. marble:[155, 342, 571, 850, 1190, 1606, 2112, 2730, 3484, 4404, 5527, 6896, 8566, 10604, 13090, 16123, 19824, 24339, 29846, 36566, 44764, 54765, 66967, 81853, 100014, 122170, 149201, 182178, 222411, 271495, 331377, 404433],
  5281. sulfur:0,
  5282. wine:0,
  5283. time:{a:96000, b:7, c:1.05, d:10080},
  5284. icon:'skin/img/city/embassy_l.png'
  5285. },
  5286. fireworker:{
  5287. buildingId:27,
  5288. maxLevel:32,
  5289. wood:[273, 353, 445, 551, 673, 813, 974, 1159, 1373, 1618, 1899, 2223, 2596, 3025, 3517, 4084, 4736, 5486, 6347, 7339, 8479, 9790, 11297, 13031, 15025, 17318, 19955, 22987, 26474, 30484, 35096, 40400],
  5290. glass:0,
  5291. marble:[135, 212, 302, 405, 526, 665, 827, 1015, 1233, 1486, 1779, 2120, 2514, 2972, 3503, 4119, 4834, 5662, 6624, 7739, 9033, 10534, 12275, 14294, 16637, 19354, 22507, 26163, 30405, 35325, 41033, 47653],
  5292. sulfur:0,
  5293. wine:0,
  5294. time:{a:125660, b:37, c:1.06, d:2628},
  5295. icon:'skin/img/city/fireworker_l.png'
  5296. },
  5297. forester:{
  5298. buildingId:18,
  5299. maxLevel:32,
  5300. wood:[250, 430, 664, 968, 1364, 1878, 2546, 3415, 4544, 6013, 7922, 10403, 13629, 17823, 23274, 30362, 39575, 51552, 67123, 87365, 113680, 147889, 192360, 250173, 325330, 423035, 550050, 715170, 929826, 1208879, 1571647, 2043247],
  5301. glass:0,
  5302. marble:[0, 104, 237, 410, 635, 928, 1309, 1803, 2446, 3282, 4368, 5781, 7617, 10004, 13108, 17142, 22387, 29204, 38068, 49590, 64569, 84042, 109357, 142266, 185047, 240664, 312965, 406956, 529145, 68799 , 894489, 1162938],
  5303. sulfur:0,
  5304. wine:0,
  5305. time:{a:72000, b:11, c:1.1, d:6120},
  5306. icon:'skin/img/city/forester_l.png'
  5307. },
  5308. glassblowing:{
  5309. buildingId:20,
  5310. maxLevel:32,
  5311. wood:[274, 467, 718, 1045, 1469, 2021, 2738, 3671, 4883, 6459, 8508, 11172, 14634, 19135, 24987, 32594, 42483, 55339, 72051, 93778, 122022, 158740, 206472, 268525, 349194, 454063, 590393, 767621, 998019, 1297536, 1686907, 2193090],
  5312. glass:0,
  5313. marble:[0, 116, 255, 436, 671, 977, 1375, 1892, 2564, 3437, 4572, 6049, 7968, 10462, 13705, 17921, 23402, 30527, 39790, 51831, 67485, 87835, 114290, 148681, 193390, 251512, 327069, 425295, 552987, 718988, 934789, 1215330],
  5314. sulfur:0,
  5315. wine:0,
  5316. time:{a:72000, b:11, c:1.1, d:6120},
  5317. icon:'skin/img/city/glassblowing_l.png'
  5318. },
  5319. museum:{
  5320. buildingId:10,
  5321. maxLevel:24,
  5322. wood:[560, 1435, 2748, 4716, 7669, 12099, 18744, 28710, 43661, 66086, 99724, 150181, 225866, 339394, 509686, 765124, 1148281, 1723017, 2585121, 3878276, 5818009, 8727609, 13092008, 19638608],
  5323. glass:0,
  5324. marble:[280, 1190, 2573, 4676, 7871, 12729, 20112, 31335, 48394, 74323, 113736, 173643, 264701, 403110, 613492, 933272, 1419338, 2158158, 3281165, 4988136, 7582731, 11526515, 17521067, 26632786],
  5325. sulfur:0,
  5326. wine:0,
  5327. time:{a:18000, b:1, c:1.1, d:14040},
  5328. icon:'skin/img/city/museum_r.png'
  5329. },
  5330. optician:{
  5331. buildingId:25,
  5332. maxLevel:32,
  5333. wood:[119, 188, 269, 362, 471, 597, 742, 912, 1108, 1335, 1600, 1906, 2261, 2673, 3152, 3706, 4350, 5096, 5962, 6966, 8131, 9482, 11050, 12868, 14978, 17424, 20263, 23555, 27374, 31805, 36944, 42905],
  5334. glass:0,
  5335. marble:[0, 35, 96, 167, 249, 345, 455, 584, 733, 905, 1106, 1338, 1608, 1921, 2283, 2704, 3192, 3759, 4416, 5178, 6062, 7087, 8276, 9656, 11257, 13113, 15267, 17765, 20663, 24025, 27924, 32448],
  5336. sulfur:0,
  5337. wine:0,
  5338. time:{a:125660, b:37, c:1.06, d:2772},
  5339. icon:'skin/img/city/optician_l.png'
  5340. },
  5341. palace:{
  5342. buildingId:11,
  5343. maxLevel:11,
  5344. wood:[712, 5824, 16048, 36496, 77392, 159184, 322768, 649936, 1304272, 2612944, 4743518],
  5345. glass:[0, 0, 0, 0, 21188, 42400, 84824, 169672, 339368, 678760, 1357544],
  5346. marble:[0, 1434, 4546, 10770, 23218, 48114, 97906, 197490, 396658, 794994, 1591666],
  5347. sulfur:[0, 0, 3089, 10301, 24725, 53573, 111269, 226661, 457445, 919013, 1842149],
  5348. wine:[0, 0, 0, 10898, 22110, 44534, 89382, 179078, 358470, 717254, 1434822],
  5349. time:{a:11520, b:1, c:1.4, d:0},
  5350. icon:'skin/img/city/palace_l.png'
  5351. },
  5352. palaceColony:{
  5353. buildingId:17,
  5354. maxLevel:11,
  5355. wood:[712, 5824, 16048, 36496, 77392, 159184, 322768, 649936, 1304272, 2612944, 4743518],
  5356. glass:[0, 0, 0, 0, 21188, 42400, 84824, 169672, 339368, 678760, 1357544],
  5357. marble:[0, 1434, 4546, 10770, 23218, 48114, 97906, 197490, 396658, 794994, 1591666],
  5358. sulfur:[0, 0, 3089, 10301, 24725, 53573, 111269, 226661, 457445, 919013, 1842149],
  5359. wine:[0, 0, 0, 10898, 22110, 44534, 89382, 179078, 358470, 717254, 1434822],
  5360. time:{a:11520, b:1, c:1.4, d:0},
  5361. icon:'skin/img/city/palaceColony_l.png'
  5362. },
  5363. port:{
  5364. buildingId:3,
  5365. maxLevel:48,
  5366. wood:[60, 150, 274, 429, 637, 894, 1207, 1645, 2106, 2735, 3537, 4492, 5689, 7103, 8850, 11094, 13731, 17062, 21097, 25965, 31810, 39190, 47998, 58713, 71955, 87627, 107102, 130777, 159020, 193938, 235849, 286515, 348718, 423990, 513947, 625161, 758178, 919694, 1116013, 1353517, 1642275, 1990224, 2411062, 2923229, 3541580, 4291524, 5199343, 6296109],
  5367. glass:0,
  5368. marble:[0, 0, 0, 0, 0, 176, 326, 540, 791, 1138, 1598, 2176, 2928, 3859, 5051, 6628, 8566, 11089, 14265, 18241, 23197, 29642, 37636, 47703, 60556, 76367, 96639, 122157, 153754, 194090, 244301, 307174, 386956, 486969, 610992, 769303, 965794, 1212791, 1523572, 1913073, 2403314, 3015689, 3782993, 4749576, 5959027, 7478201, 9383420, 11768772],
  5369. sulfur:0,
  5370. wine:0,
  5371. time:{a:50400, b:23, c:1.15, d:1512},
  5372. loadingSpeed:[30, 60, 93, 129, 169, 213, 261, 315, 373, 437, 508, 586, 672, 766, 869, 983, 1108, 1246, 1398, 1565, 1748, 1950, 2172, 2416, 2685, 2980, 3305, 3663, 4056, 4489, 4965, 5488, 6064, 6698, 7394, 8161, 9004, 9931, 10951, 12073, 13308, 14666, 16159, 17802, 19609, 21597, 23784, 26189],
  5373. icon:'skin/img/city/port_l.png'
  5374. },
  5375. safehouse:{
  5376. buildingId:16,
  5377. maxLevel:32,
  5378. wood:[113, 248, 402, 578, 779, 1007, 1267, 1564, 1903, 2288, 2728, 3230, 3801, 4453, 5195, 6042, 7008, 8108, 9363, 10793, 12423, 14282, 16401, 18816, 21570, 24709, 28288, 32368, 37019, 42321, 48365, 55255],
  5379. glass:0,
  5380. marble:[0, 0, 0, 129, 197, 275, 366, 471, 593, 735, 900, 1090, 1312, 1569, 1866, 2212, 2613, 3078, 3617, 4243, 4968, 5810, 6787, 7919, 9233, 10758, 12526, 14577, 16956, 19716, 22917, 26631],
  5381. sulfur:0,
  5382. wine:0,
  5383. time:{a:96000, b:7, c:1.05, d:12960},
  5384. icon:'skin/img/city/safehouse_l.png'
  5385. },
  5386. shipyard:{
  5387. buildingId:5,
  5388. maxLevel:32,
  5389. wood:[105, 202, 324, 477, 671, 914, 1222, 1609, 2096, 2711, 3485, 4460, 5689, 7238, 9190, 11648, 14746, 18650, 23568, 29765, 37573, 47412, 59808, 75428, 95108, 119906, 151151, 190520, 240124, 302626, 381378, 480605],
  5390. glass:0,
  5391. marble:[0, 0, 0, 0, 0, 778, 1052, 1397, 1832, 2381, 3071, 3942, 5038, 6420, 8161, 10354, 13118, 16601, 20989, 26517, 33484, 42261, 53321, 67256, 84814, 106938, 134814, 169937, 214192, 269954, 340214, 428741],
  5392. sulfur:0,
  5393. wine:0,
  5394. time:{a:64800, b:7, c:1.05, d:7128},
  5395. icon:'skin/img/city/shipyard_l.png'
  5396. },
  5397. stonemason:{
  5398. buildingId:19,
  5399. maxLevel:32,
  5400. wood:[274, 467, 718, 1045, 1469, 2021, 2738, 3671, 4883, 6459, 8508, 11172, 14634, 19135, 24987, 32594, 42483, 55339, 72051, 93778, 122022, 158740, 206472, 268525, 349194, 454063, 590393, 767621, 998019, 1297536, 1686907, 2193090],
  5401. glass:0,
  5402. marble:[0, 116, 255, 436, 671, 977, 1375, 1892, 2564, 3437, 4572, 6049, 7968, 10462, 13705, 17921, 23402, 30527, 39790, 51831, 67485, 87835, 114290, 148681, 193390, 251512, 327069, 425295, 552987, 718988, 934789, 1215330],
  5403. sulfur:0,
  5404. wine:0,
  5405. time:{a:72000, b:11, c:1.1, d:6120},
  5406. icon:'skin/img/city/stonemason_l.png'
  5407. },
  5408. temple:{
  5409. buildingId:28,
  5410. maxLevel:32,
  5411. wood:[216, 228, 333, 465, 598, 760, 958, 1197, 1432, 1773, 2112, 2512, 3082, 3655, 4458, 5126, 6232, 7167, 8688, 10247, 11784, 14229, 16753, 19266, 23186, 26664, 32027, 36831, 43257, 50782, 59591, 68529],
  5412. glass:[173, 190, 290, 423, 567, 752, 989, 1290, 1610, 2080, 2586, 3210, 4109, 5084, 6471, 7765, 9851, 11821, 14952, 18402, 22082, 27824, 34184, 41020, 51514, 61817, 77477, 92972, 113941, 139577, 170911, 205093],
  5413. marble:0,
  5414. sulfur:0,
  5415. wine:0,
  5416. time:{a:2160, b:1, c:1.1, d:0},
  5417. icon:'skin/img/city/temple_l.png'
  5418. },
  5419. blackMarket:{
  5420. buildingId:29,
  5421. maxLevel:25,
  5422. wood:[440, 887, 1360, 1890, 2516, 3288, 4263, 5505, 7086, 9086, 11590, 14691, 18489, 23088, 28600, 35143, 42839, 51820, 62218, 74175, 87838, 103356, 120888, 140596, 162647],
  5423. glass:0,
  5424. marble:[260, 525, 807, 1126, 1509, 1988, 2601, 3390, 4403, 5693, 7315, 9331, 11807, 14812, 18420, 22708, 27757, 33654, 40486, 48348, 57334, 67546, 79087, 92064, 106587],
  5425. sulfur:0,
  5426. wine:0,
  5427. time:{a:2160, b:1, c:1.1, d:0},
  5428. icon:'skin/img/city/blackmarket_l.png'
  5429. },
  5430. marineChartArchive:{
  5431. buildingId:32,
  5432. maxLevel:25,
  5433. wood:[440, 887, 1360, 1890, 2516, 3288, 4263, 5505, 7086, 9086, 11590, 14691, 18489, 23088, 28600, 35143, 42839, 51820, 62218, 74175, 87838, 103356, 120888, 140596, 162647],
  5434. glass:0,
  5435. marble:[260, 525, 807, 1126, 1509, 1988, 2601, 3390, 4403, 5693, 7315, 9331, 11807, 14812, 18420, 22708, 27757, 33654, 40486, 48348, 57334, 67546, 79087, 92064, 106587],
  5436. sulfur:0,
  5437. wine:0,
  5438. time:{a:2160, b:1, c:1.1, d:0},
  5439. icon:'skin/img/city/marinechartarchive_l.png'
  5440. },
  5441. tavern:{
  5442. buildingId:9,
  5443. maxLevel:48,
  5444. wood:[101, 222, 367, 541, 750, 1001, 1302, 1663, 2097, 2617, 3241, 3990, 4888, 5967, 7261, 8814, 10678, 12914, 15598, 18818, 22683, 27320, 32885, 39562, 47576, 57192, 68731, 82578, 99194, 119134, 143061, 171774, 206230, 247577, 297193, 356732, 428179, 513916, 616800, 740261, 888414, 1066197, 1279538, 1535546, 1842756, 2211408, 2653790, 3184649],
  5445. glass:0,
  5446. marble:[0, 0, 0, 94, 122, 158, 206, 267, 348, 452, 587, 764, 993, 1290, 1677, 2181, 2835, 3685, 4791, 6228, 8097, 10526, 13684, 17789, 23125, 30063, 39082, 50806, 66048, 85862, 111621, 145107, 188640, 245232, 318801, 414441, 538774, 700406, 910528, 1183686, 1538792, 2000429, 2600558, 3380726, 4394943, 5713427, 7427454, 9655691],
  5447. sulfur:0,
  5448. wine:0,
  5449. time:{a:10800, b:1, c:1.06, d:10440},
  5450. icon:'skin/img/city/taverne_r.png',
  5451. wineUse:[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, 1203, 1280, 1362]
  5452. },
  5453. townHall:{
  5454. buildingId:0,
  5455. maxLevel:48,
  5456. wood:[0, 158, 335, 623, 923, 1390, 2015, 2706, 3661, 4776, 6173, 8074, 10281, 13023, 16424, 20986, 25423, 32285, 40232, 49286, 61207, 74804, 93956, 113035, 141594, 170213, 210011, 258875, 314902, 387657, 471194, 572581, 695617, 854729, 1037816, 1274043, 1529212, 1876201, 2276286, 2761291, 3384434, 4061704, 4975980, 6032502, 7312524, 8863183, 10846842, 13016622],
  5457. glass:0,
  5458. marble:[0, 0, 0, 0, 285, 551, 936, 1411, 2091, 2945, 4072, 5664, 7637, 10214, 13575, 18254, 23250, 31022, 40599, 52216, 68069, 87316, 115101, 145326, 191053, 241039, 312128, 403825, 515593, 666229, 850031, 1084293, 1382827, 1783721, 2273687, 2930330, 3692591, 4756439, 6058643, 7716366, 9929885, 12512055, 16094038, 20485823, 26073282, 33181278, 42636729, 53722706],
  5459. sulfur:0,
  5460. wine:0,
  5461. time:{a:1800, b:1, c:1.17, d:-1080},
  5462. icon:'skin/img/city/townhall_l.png'
  5463. },
  5464. vineyard:{
  5465. buildingId:26,
  5466. maxLevel:32,
  5467. wood:[339, 423, 520, 631, 758, 905, 1074, 1269, 1492, 1749, 2045, 2384, 2775, 3225, 3741, 4336, 5019, 5805, 6709, 7749, 8944, 10319, 11900, 13718, 15809, 18214, 20979, 24159, 27816, 32021, 36858, 42419],
  5468. glass:0,
  5469. marble:[123, 198, 285, 387, 504, 640, 798, 981, 1194, 1440, 1726, 2058, 2443, 2889, 3407, 4008, 4705, 5513, 6450, 7538, 8800, 10263, 11961, 13930, 16214, 18864, 21938, 25503, 29639, 34437, 40002, 46458],
  5470. sulfur:0,
  5471. wine:0,
  5472. time:{a:125660, b:37, c:1.06, d:2232},
  5473. icon:'skin/img/city/vineyard_l.png'
  5474. },
  5475. wall:{
  5476. buildingId:8,
  5477. maxLevel:48,
  5478. wood:[114, 361, 657, 1012, 1439, 1951, 2565, 3302, 4186, 5247, 6521, 8049, 9882, 12083, 14724, 17892, 21695, 26258, 31733, 38304, 46189, 55650, 67004, 80629, 96979, 116599, 140143, 168395, 202298, 242982, 291802, 350387, 420688, 505050, 606284, 727765, 873542, 1048474, 1258393, 1510295, 1812578, 2175318, 2610605, 3132950, 3759764, 4511941, 5414554, 6497688],
  5479. glass:0,
  5480. marble:[0, 203, 516, 892, 1344, 1885, 2535, 3315, 4251, 5374, 6721, 8338, 10279, 12608, 15402, 18755, 22779, 27607, 33402, 40355, 48699, 58711, 70726, 85144, 102446, 123208, 148122, 178019, 213896, 256948, 308610, 370605, 444998, 534271, 641398, 769950, 924213, 1109329, 1331467, 1598033, 1917913, 2301768, 2762394, 3315146, 3978448, 4774411, 5729566, 6875751],
  5481. sulfur:0,
  5482. wine:0,
  5483. time:{a:57600, b:11, c:1.1, d:3240},
  5484. icon:'skin/img/city/wall.png'
  5485. },
  5486. warehouse:{
  5487. buildingId:7,
  5488. maxLevel:40,
  5489. wood:[160, 288, 442, 626, 847, 1113, 1431, 1813, 2272, 2822, 3483, 4275, 5226, 6368, 7737, 9380, 11353, 13719, 16559, 19967, 24056, 28963, 34852, 41918, 50398, 60574, 72784, 87437, 105021, 126121, 151441, 181825, 218286, 262039, 314543, 377548, 453153, 543880, 652752, 783398],
  5490. glass:0,
  5491. marble:[0, 0, 0, 96, 211, 349, 515, 714, 953, 1240, 1584, 1997, 2492, 3086, 3800, 4656, 5683, 6915, 8394, 10169, 12299, 14855, 17922, 21602, 26019, 31319, 37678, 45310, 54468, 65458, 78645, 94471, 113461, 136249, 163595, 196409, 235787, 283041, 339745, 407790],
  5492. sulfur:0,
  5493. wine:0,
  5494. time:{a:2880, b:1, c:1.14, d:2160},
  5495. icon:'skin/img/city/warehouse_l.png'
  5496. },
  5497. winegrower:{
  5498. buildingId:21,
  5499. maxLevel:32,
  5500. wood:[274, 467, 718, 1045, 1469, 2021, 2738, 3671, 4883, 6459, 8508, 11172, 14634, 19135, 24987, 32594, 42483, 55339, 72051, 93778, 122022, 158740, 206472, 268525, 349194, 454063, 590393, 767621, 998019, 1297536, 1686907, 2193090],
  5501. glass:0,
  5502. marble:[0, 116, 255, 436, 671, 977, 1375, 1892, 2564, 3437, 4572, 6049, 7968, 10462, 13705, 17921, 23402, 30527, 39790, 51831, 67485, 87835, 114290, 148681, 193390, 251512, 327069, 425295, 552987, 718988, 934789, 1215330],
  5503. sulfur:0,
  5504. wine:0,
  5505. time:{a:72000, b:11, c:1.1, d:6120},
  5506. icon:'skin/img/city/winegrower_l.png'
  5507. },
  5508. workshop:{
  5509. buildingId:15,
  5510. maxLevel:32,
  5511. wood:[220, 383, 569, 781, 1023, 1299, 1613, 1972, 2380, 2846, 3377, 3982, 4672, 5458, 6355, 7377, 8542, 9870, 11385, 13111, 15079, 17322, 19880, 22796, 26119, 29909, 34228, 39153, 44766, 51166, 58462, 66779],
  5512. glass:0,
  5513. marble:[95, 167, 251, 349, 461, 592, 744, 920, 1125, 1362, 1637, 1956, 2326, 2755, 3253, 3831, 4501, 5278, 6180, 7226, 8439, 9847, 11479, 13373, 15570, 18118, 21074, 24503, 28481, 33095, 38447, 44656],
  5514. sulfur:0,
  5515. wine:0,
  5516. time:{a:96000, b:7, c:1.05, d:11880},
  5517. icon:'skin/img/city/workshop_l.png'
  5518. },
  5519. pirateFortress:{
  5520. buildingId:30,
  5521. maxLevel: 30,
  5522. wood:[450, 906, 1389, 1935, 2593, 3427, 4516, 5950, 7834, 10284, 13430, 17415, 22394, 28534, 36015, 45029, 55779, 68482, 83366, 100671, 120648, 143562, 169686, 199309, 232729, 270255, 312210, 358926, 410748, 468032],
  5523. glass:0,
  5524. marble:[250, 505, 783, 1112, 1534, 2103, 2883, 3949, 5388, 7296, 9782, 12964, 16970, 21938, 28019, 35370, 44162, 54573, 66793, 81020, 97463, 116341, 137883, 162325, 189915, 220912, 255580, 294197, 337048, 384429],
  5525. sulfur:0,
  5526. wine:0,
  5527. time:{a:0, b:0, c:0, d:0},
  5528. icon:'skin/img/city/pirateFortress_l.png'
  5529. }
  5530. }
  5531. };
  5532. Constant.buildingOrder = {
  5533. growth : [Constant.Buildings.TOWN_HALL, Constant.Buildings.PALACE, Constant.Buildings.GOVERNORS_RESIDENCE, Constant.Buildings.TAVERN, Constant.Buildings.MUSEUM, Constant.Buildings.MARINECHARTARCHIVE],
  5534. research : [Constant.Buildings.ACADEMY, Constant.Buildings.WORKSHOP, Constant.Buildings.TEMPLE],
  5535. diplomacy: [Constant.Buildings.EMBASSY],
  5536. trading : [Constant.Buildings.WAREHOUSE, Constant.Buildings.BLACKMARKET, Constant.Buildings.DUMP, Constant.Buildings.TRADING_PORT, Constant.Buildings.TRADING_POST],
  5537. military : [Constant.Buildings.WALL, Constant.Buildings.HIDEOUT, Constant.Buildings.BARRACKS, Constant.Buildings.SHIPYARD, Constant.Buildings.PIRATE_FORTRESS],
  5538. wood : [Constant.Buildings.FORESTER, Constant.Buildings.CARPENTER],
  5539. wine : [Constant.Buildings.WINERY, Constant.Buildings.VINEYARD],
  5540. marble : [Constant.Buildings.STONEMASON, Constant.Buildings.ARCHITECT],
  5541. crystal : [Constant.Buildings.GLASSBLOWER, Constant.Buildings.OPTICIAN],
  5542. sulfur : [Constant.Buildings.ALCHEMISTS_TOWER, Constant.Buildings.FIREWORK_TEST_AREA]
  5543. };
  5544. Constant.altBuildingOrder = {
  5545. growth : [Constant.Buildings.TOWN_HALL, 'colonyBuilding', Constant.Buildings.PALACE, Constant.Buildings.GOVERNORS_RESIDENCE, Constant.Buildings.TAVERN, Constant.Buildings.MUSEUM, Constant.Buildings.MARINECHARTARCHIVE],
  5546. research : [Constant.Buildings.ACADEMY, Constant.Buildings.WORKSHOP, Constant.Buildings.TEMPLE],
  5547. diplomacy : [Constant.Buildings.EMBASSY],
  5548. trading : [Constant.Buildings.WAREHOUSE, Constant.Buildings.BLACKMARKET, Constant.Buildings.DUMP, Constant.Buildings.TRADING_PORT, Constant.Buildings.TRADING_POST],
  5549. military : [Constant.Buildings.WALL, Constant.Buildings.HIDEOUT, Constant.Buildings.BARRACKS, Constant.Buildings.SHIPYARD, Constant.Buildings.PIRATE_FORTRESS],
  5550. production: [Constant.Buildings.FORESTER, 'productionBuilding', Constant.Buildings.WINERY, Constant.Buildings.STONEMASON, Constant.Buildings.GLASSBLOWER, Constant.Buildings.ALCHEMISTS_TOWER],
  5551. reducton : [Constant.Buildings.CARPENTER, Constant.Buildings.VINEYARD, Constant.Buildings.ARCHITECT, Constant.Buildings.OPTICIAN, Constant.Buildings.FIREWORK_TEST_AREA]
  5552. };
  5553. Constant.unitOrder = {
  5554. army_front_line: [Constant.Military.HOPLITE, Constant.Military.STEAM_GIANT],
  5555. army_flank : [Constant.Military.SPEARMAN, Constant.Military.SWORDSMAN],
  5556. army_ranged : [Constant.Military.SLINGER, Constant.Military.ARCHER, Constant.Military.MARKSMAN],
  5557. army_seige : [Constant.Military.RAM, Constant.Military.CATAPULT, Constant.Military.MORTAR],
  5558. army_air : [Constant.Military.GYROCOPTER, Constant.Military.BALLOON_BOMBADIER],
  5559. army_support : [Constant.Military.COOK, Constant.Military.DOCTOR],
  5560. navy_front_line: [Constant.Military.FLAME_THROWER, Constant.Military.STEAM_RAM],
  5561. navy_flank : [Constant.Military.RAM_SHIP],
  5562. navy_ranged : [Constant.Military.BALLISTA_SHIP, Constant.Military.CATAPULT_SHIP, Constant.Military.MORTAR_SHIP],
  5563. navy_seige : [Constant.Military.SUBMARINE, Constant.Military.ROCKET_SHIP],
  5564. navy_air : [Constant.Military.PADDLE_SPEEDBOAT, Constant.Military.BALLOON_CARRIER],
  5565. navy_support : [Constant.Military.TENDER]
  5566. };
  5567.  
  5568. /***********************************************************************************************************************
  5569. * Main Init
  5570. **********************************************************************************************************************/
  5571. if(debug) {
  5572. delete unsafeWindow.console;
  5573. unsafeWindow.SITR = {
  5574. s : SITR,
  5575. db : database,
  5576. ikariam : ikariam,
  5577. render : render,
  5578. events : events,
  5579. utils : Utils,
  5580. Constant: Constant,
  5581. $ : $,
  5582. get tip(){return $('.breakdown_table').text().replace(/\s\s/g,' ').replace(/\s\s/g,' ').replace(/\s\s/g,' ').replace(/\s\s/g,' ').replace(/\s\s/g,' ').replace(/\s\s/g,' ').replace(/\s\s/g,' ').replace(/\s\s/g,' ').replace(/\s\s/g,' ').replace(/\s\s/g,' ').replace(/\s\s/g,' ').replace(/\s\s/g,' ')}
  5583. }
  5584. }
  5585.  
  5586. SITR.Init();
  5587. $(function() {
  5588. var bgViewId = $('body').attr('id');
  5589. if(!(bgViewId === 'city' || bgViewId === 'island' || bgViewId === 'worldmap_iso' || !$('backupLockTimer').length)) {
  5590. return false
  5591. }
  5592.  
  5593. (function init(model, data, local, ajax){
  5594. var mod, dat, loc, aj;
  5595. mod = !!unsafeWindow.ikariam && !!unsafeWindow.ikariam.model;
  5596. dat = !!unsafeWindow.ikariam && !!unsafeWindow.ikariam.model.relatedCityData;
  5597. loc = !!unsafeWindow.LocalizationStrings;
  5598. aj = !!unsafeWindow.ikariam.controller && !!unsafeWindow.ikariam.controller.executeAjaxRequest && !!unsafeWindow.ajaxHandlerCallFromForm;
  5599. if (dat && !data){
  5600. events(Constant.Events.CITYDATA_AVAILABLE).pub();
  5601. }
  5602. if (mod && dat && !model && !data){
  5603. events(Constant.Events.MODEL_AVAILABLE).pub()
  5604. }
  5605. if (loc && !local){
  5606. events(Constant.Events.LOCAL_STRINGS_AVAILABLE).pub()
  5607. }
  5608. if (aj && !ajax){
  5609. unsafeWindow.ajaxHandlerCallFromForm = function(ajaxHandlerCallFromForm) {
  5610. return function cAjaxHandlerCallFromForm(form) {
  5611. events('formSubmit').pub(form);
  5612. return ajaxHandlerCallFromForm.apply(this, arguments);
  5613. };
  5614. }(unsafeWindow.ajaxHandlerCallFromForm);
  5615.  
  5616. unsafeWindow.ikariam.controller.executeAjaxRequest = function(execAjaxRequest) {
  5617. return function cExecuteAjaxRequest() {
  5618. var args = $.makeArray(arguments);
  5619. args.push(undefined);
  5620. if(!args[1]) {
  5621. args[1] = function customAjaxCallback(responseText) {
  5622. var responder = unsafeWindow.ikariam.getClass(unsafeWindow.ajax.Responder, responseText);
  5623. unsafeWindow.ikariam.controller.ajaxResponder = responder;
  5624. events('ajaxResponse').pub(responder.responseArray);
  5625. unsafeWindow.response = responder
  5626. }
  5627. }
  5628. var ret = execAjaxRequest.apply(this, args)
  5629. };
  5630. }(unsafeWindow.ikariam.controller.executeAjaxRequest);
  5631. }
  5632. if (!(mod && loc && dat && aj)){
  5633. events.scheduleAction(init.bind(null, mod, loc, dat, aj),1000);
  5634. }
  5635. else {
  5636. var initialAjax = [];
  5637. $('script').each(function(index, script) {
  5638. var match = /ikariam.getClass\(ajax.Responder, (.*)\);/.exec(script.innerHTML);
  5639. if(match) {
  5640. events('ajaxResponse').pub(JSON.parse(match[1] || []));
  5641. return false;
  5642. }
  5643. });
  5644. }
  5645. })();
  5646. });
  5647. })(jQuery);