IDEAL Scripts

All IDEAL Scripts for idealclan.eu merged into one

Versión del día 10/07/2020. Echa un vistazo a la versión más reciente.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

You will need to install an extension such as Tampermonkey to install this script.

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name        IDEAL Scripts
// @version     1.22
// @description All IDEAL Scripts for idealclan.eu merged into one
// @author      Orrie
// @namespace   http://idealclan.eu/viewtopic.php?f=7&t=1791#p57645
// @icon        https://i.imgur.com/9GeRjIp.png
// @include     http*://*idealclan.eu/*
// @grant       GM_xmlhttpRequest
// @grant       GM.xmlHttpRequest
// @connect     eu.wargaming.net
// @connect     api.worldoftanks.eu
// @connect     api.twitch.tv
// @require     https://greasyfork.org/scripts/18946-tablesort/code/Tablesort.js?version=120660
// @require     https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @license     Mr Sexii License
// ==/UserScript==
(function() {
	// global variables
	const date = new Date();
	let battleTable, updateInterval, style, sortTable = false, time, styleDynBattles, styleDynFinales, inputSpan, timeJump = false, timeInterval, styleDynTimezone;
	// script variables
	const bs = {
		href: document.location.href,
		vers: ((GM.info) ? GM.info.script.version : ""),
		cw: {
			status: JSON.parse(localStorage.getItem("battles_force")) || false,
			event: false,
			gold: true,
			fame: 400,
			tier: "Ɵ",
			bats: "Ɵ",
			elo: "Ɵ",
			current: 0,
			globalmap: false
		},
		dyn: {
			conc: {},
			prov: [],
			plan: 0,
			check: 0,
			gold: 0
		},
		clan: {
			ideal: 500010805,
			id: JSON.parse(localStorage.getItem("battles_clanid")) || 500010805,
			tag: "Ɵ",
			emblem: "Ɵ",
			color: "Ɵ"
		},
		table: {
			static: 10,
			eu: [17, 18, 19, 20, 21, 22, 23, 24],
			c: "",
			s: []
		},
		front_loc: {
			"league1": " (BF)",
			"league2": " (AF)",
			"league3": " (EF)"
		},
		app_id: "a7595640a90bf2d19065f3f2683b171c",
		web: {
			// browser detection
			gecko: typeof InstallTrigger !== 'undefined',
			chrome: !!window.chrome && !!window.chrome.webstore
		},
		time: {
			h: date.getHours(),
			m: date.getMinutes(),
			o: (date.getTimezoneOffset() > 0 ? -Math.abs(date.getTimezoneOffset()) : Math.abs(date.getTimezoneOffset())) / 60
		},
		debug: false // document.getElementsByClassName("headerbnl")[0].innerHTML.match(/Orrie/) ? true : false
	};
	bs.api = {
		event: `https://api.worldoftanks.eu/wot/globalmap/events/?application_id=${bs.app_id}&limit=1`,
		clan: `https://eu.wargaming.net/globalmap/game_api/clan/${bs.clan.id}/battles`,
		bats: "https://eu.wargaming.net/globalmap/game_api/map_fill_info?aliases=",
		tourney: "https://eu.wargaming.net/globalmap/game_api/tournament_info?alias=",
		prov: "https://eu.wargaming.net/globalmap/game_api/province_info?alias=",
		provs: `https://api.worldoftanks.eu/wot/globalmap/clanprovinces/?application_id=${bs.app_id}&clan_id=${bs.clan.id}`,
		divs: "https://eu.wargaming.net/globalmap/game_api/wot/clan_tactical_data", // need authentication from global map
		raids: "https://eu.wargaming.net/globalmap/game_api/wot/raids" // need authentication from global map
	};
	bs.time.r = ((bs.time.m >= 15 && bs.time.m <= 45) ? [bs.time.h, "30"] : ((bs.time.m <= 15) ? [bs.time.h, "00"] : [(bs.time.h + 1), "00"]));
	bs.time.t = `${bs.time.r[0]}_${bs.time.r[1]}`;
	if (bs.debug) {
		console.info("script", bs, new Date().toLocaleTimeString("en-GB"));
	}
	// image codes and stream list
	const img = {
		main: "data:image/png;base64,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"
	},
	clans = [
		"<option value='500010805'>IDEAL</option>",
		"<option value='500003585'>RSOP</option>",
		"<option value='500012667'>-PJ-</option>",
		"<option value='500025989'>FAME</option>",
		"<option value='500000013'>CSA</option>"
	];
	// script functions
	const sf = {
		elem(tag, attributes, children) {
			// element creation
			const element = document.createElement(tag);
			if (attributes) {
				for (let _e_k = Object.keys(attributes), _e = _e_k.length; _e > 0; _e--) {
					element[_e_k[_e - 1]] = attributes[_e_k[_e - 1]];
				}
			}
			if (children) {
				if (children.nodeType) {
					element.appendChild(children);
				}
				else {
					for (let _c = 0, _c_len = children.length; _c < _c_len; _c++) {
						element.appendChild(children[_c]);
					}
				}
			}
			return element;
		},
		cw: {
			// battle scheduler
			handlerEvent(data) {
				// event checker
				// check if active event exists
				const event = (data.data) ? data.data[0] : "error";
				if (event.status == "ACTIVE" || !bs.cw.status) {
					if (event.status == "ACTIVE") {
						bs.cw.event = true;
						bs.cw.tier = 10;
						document.getElementById('js-eventName').innerHTML = `${event.event_name.replace(/_/g," ")} &#8226; `;
					}
					sf.request({name: "mainData", api: bs.api.clan, handler: sf.cw.handlerMain, mode: "cw"});
					document.getElementById('js-tableStats').classList.remove("b-display-none");
				}
				else {
					// empty table
					battleTable.children[1].innerHTML = "";
					battleTable.children[1].appendChild(sf.elem("tr", {
						className: "t-cwText",
						innerHTML: "<td colspan='23'>See you next time.</td>"
					}));
					clearInterval(updateInterval);
				}
				// insert update timestamp
				document.getElementById('js-batttleUpdate').textContent = new Date().toLocaleTimeString("en-GB");
			},
			handlerMain({clan, battles, planned_battles}) {
				// main handler
				const battleProvinces = [],
				battleFragment = document.createDocumentFragment();
				let battle, battleTime;
				// store data
				bs.clan.tag = clan.tag;
				bs.clan.emblem = clan.emblem_url;
				bs.clan.color = clan.color;
				bs.cw.bats = clan.appointed_battles_count;
				bs.cw.current = battles.length;
				bs.cw.elo = {
					6: clan.elo_rating_6,
					8: clan.elo_rating_8,
					10: clan.elo_rating_10
				};
				style.textContent += `.t-clantag {color: ${bs.clan.color};}`;
				// go through battles and planned battles
				for (let _b = 0, _b_len = battles.length; _b < _b_len; _b++) {
					battle = battles[_b];
					if (!battleProvinces.includes(battle.province_id)) {
						battleProvinces.push(battle.province_id);
						battleTime = [sf.cw.time(parseFloat(battle.battle_time.match(/\d+/g)[3])), battle.battle_time.match(/\d+/g)[4], battle.battle_time.match(/\d+/g)[5]];
						battleFragment.appendChild(sf.elem("tr", {
							className: `battle ${battle.province_id} attack`,
							innerHTML: `<td><a target='_blank' href='https://eu.wargaming.net/globalmap/#province/${battle.province_id}'>${battle.province_name}</a> [<a class='t-tournament' target='_blank' href='https://eu.wargaming.net/globalmap/#tournament/${battle.province_id}'>&#9876;</a>]</td><td>${sf.cw.mapFix(battle.arena_name)}</td><td></td><td class='t-gold'><span></span><span class='icon icon_main icon_gold'></span></td><td class='t-fame'>Ɵ</td><td></td><td><span></span><span></span></td><td id='${battle.enemy.id}'><a target='_blank' href='https://eu.wargaming.net/clans/${battle.enemy.id}/'>[${battle.enemy.tag}] <img src='${battle.enemy.emblem_url}'></a><span class='t-elo'>(${battle.enemy[`elo_rating_${(bs.cw.event) ? bs.cw.tier : "10"}`]})</span></td><td class='t-nextBattle' data-sort='${battleTime[0] === 0 ? battleTime[0]+25 : battleTime[0]}${battleTime[1]}.${battleTime[2]}'>${battleTime[0]}:${battleTime[1]}:${battleTime[2]}</td><td class='t-battle'>Ɵ</td><td class='t-battle t-border'>Ɵ</td>${bs.table.c}`
						}));
						if (battle.round_number) {
							sf.request({name: "freepassData", api:`${bs.api.tourney+battle.province_id}&round=${battle.round_number}`, handler: sf.cw.handlerFreepass, mode: "cw", province: battle.province_id});
						}
					}
				}
				for (let _bp = 0, _bp_len = planned_battles.length; _bp < _bp_len; _bp++) {
					battle = planned_battles[_bp];
					if (!battleProvinces.includes(battle.province_id)) {
						battleProvinces.push(battle.province_id);
						battleTime = [sf.cw.time(parseFloat(battle.battle_time.match(/\d+/g)[3])), battle.battle_time.match(/\d+/g)[4], battle.battle_time.match(/\d+/g)[5]];
						battleFragment.appendChild(sf.elem("tr", {
							className: `battle ${battle.province_id} attack`,
							innerHTML: `<td><a target='_blank' href='https://eu.wargaming.net/globalmap/#province/${battle.province_id}'>${battle.province_name}</a> [<a class='t-tournament' target='_blank' href='https://eu.wargaming.net/globalmap/#tournament/${battle.province_id}'>&#9876;</a>]</td><td>${sf.cw.mapFix(battle.arena_name)}</td><td></td><td class='t-gold'><span>${battle.province_revenue}</span><span class='icon icon_main icon_gold'></span></td><td class='t-fame'>Ɵ</td><td></td><td><span></span><span></span></td><td>Not Started</td><td class='t-nextBattle' data-sort='${battleTime[0] === 0 ? battleTime[0]+25 : battleTime[0]}${battleTime[1]}.${battleTime[2]}'>${battleTime[0] === 0 ? "00" : battleTime[0]}:${battleTime[1]}:${battleTime[2]}</td><td class='t-battle'>Ɵ</td><td class='t-battle t-border'>Ɵ</td>${bs.table.c}`
						}));
						if (battle.is_attacker) {
							sf.request({name: "freepassData", api: `${bs.api.tourney+battle.province_id}&round=1`, handler: sf.cw.handlerFreepass, mode: "cw", province: battle.province_id});
						}
					}
				}
				// show foes and battle count if clan has any battles and remove loading indicator
				if (bs.cw.bats > 0) {
					// style.textContent += ".t-battle {display: table-cell !important;}";
					battleTable.children[1].innerHTML = ""; // empty table
				}
				battleTable.children[1].appendChild(battleFragment);
				// insert clan name
				document.getElementById('js-clan').innerHTML = `<span class='t-clantag'>[${bs.clan.tag}]</span> ${clan.name} <img src='${bs.clan.emblem}'> &#8226; `;
				// insert battle count
				document.getElementById('js-battles').textContent = bs.cw.current;
				// insert battle count
				document.getElementById('js-battlesPlan').textContent = bs.cw.bats;
				// send request for detailed battle information
				if (bs.cw.bats > 0) {
					sf.request({name: "batsData", api: bs.api.bats + battleProvinces.join("&aliases="), handler: sf.cw.handlerBats, mode: "cw"});
				}
				// send request for clan provinces
				sf.request({name: "provsData", api: bs.api.provs, handler: sf.cw.handlerProvs, mode: "cw"});
			},
			handlerBats(data, isPlanned) {
				// battles handler
				for (let _bd = 0, _bd_len = data.data.length; _bd < _bd_len; _bd++) {
					const battle = data.data[_bd],
					battleRow = document.getElementsByClassName(battle.alias)[0],
					enemyID = battleRow.children[7].id,
					battleType = ((battle.owner_clan_id == bs.clan.id) ? "Defense" : ((battle.owner_clan_id == enemyID) ? "Owner" : "Attack")),
					primeTime = [sf.cw.time(parseFloat(battle.primetime.match(/\d+/g)[0])), battle.primetime.match(/\d+/g)[1], parseFloat(battle.primetime.match(/\d+/g)[0])];
					battleRow.dataset.primeTime = JSON.stringify(primeTime);
					if (battleType == "Defense") {
						battleRow.classList.remove("attack");
						battleRow.classList.add("defense");
					}
					// modify cells
					battleRow.children[2].textContent = `${primeTime[0]}:${primeTime[1]}`;
					battleRow.children[2].dataset.sort = `${primeTime[0]}${primeTime[1]}`;
					battleRow.children[3].firstElementChild.textContent = battle.revenue;
					battleRow.children[6].firstElementChild.textContent = battleType;
					if (battleRow.children[8].textContent == "") {
						battleRow.children[8].textContent = `${primeTime[0]}:${primeTime[1]}:00`;
						battleRow.children[8].dataset.sort = `${primeTime[0]}${primeTime[1]}`;
					}
					// get correct battle count and schedule
					sf.request({name: "tourneyData", api: `${bs.api.tourney+battle.alias}&round=1`, handler: sf.cw.handlerTourney, mode: "cw", province: battle.alias});
					// get province famepoints if event
					if (bs.cw.event) {
						sf.request({name: "provData", api: bs.api.prov + battle.alias, handler: sf.cw.handlerProv, mode: "cw", province: battle.alias});
					}
				}
				// refresh table
				sortTable.refresh();
			},
			handlerTourney(data, isPlanned) {
				// tournament handler
				const battleRow = document.getElementsByClassName(data.province_id)[0],
				ownerClan = (data.owner) ? (data.owner.id == bs.clan.id) || false : false,
				isAuction = battleRow.classList.contains("auction");
				let primeTime,
				battleResult = "Ongoing",
				cellOwnerTime = false,
				attackers = [data.pretenders, 0];
				bs.dyn.check++;
				primeTime = [sf.cw.time(parseFloat(data.start_time.match(/\d+/g)[0])), data.start_time.match(/\d+/g)[1], parseFloat(data.start_time.match(/\d+/g)[0])];
				battleRow.dataset.primeTime = JSON.stringify(primeTime);
				// check attackers
				if (attackers[0].length) {
					const _pre_len = attackers[0].length,
					attacker_ids = [];
					for (let _pre = 0; _pre < _pre_len; _pre++) {
						attacker_ids.push(attackers[0][_pre].id);
					}
					if (!ownerClan && !attacker_ids.includes(bs.clan.id)) {
						//battleRow.remove();
					}
				}
				else if (data.battles) {
					const _bat_len = data.battles.length,
					attacker_ids = [];
					for (let _bat = 0; _bat < _bat_len; _bat++) {
						const battle = data.battles[_bat];
						attacker_ids.push(battle.first_competitor.id);
						if (battle.second_competitor) {
							attacker_ids.push(data.battles[_bat].second_competitor.id);
						}
					}
					if (!ownerClan && !attacker_ids.includes(bs.clan.id)) {
						//battleRow.remove();
					}
				}
				if (data.is_superfinal) {
					attackers = 1;
				}
				else if (attackers[0].length) {
					attackers = attackers[0].length;
				}
				else {
					attackers = attackers[1];
					for (let _bc = 0, _bc_len = data.battles.length; _bc < _bc_len; _bc++) {
						attackers += ((data.battles[_bc].is_fake) ? 1 : 2);
					}
				}
				if (isAuction && battleRow.children[7].innerHTML == "Not Started") {
					attackers = data.size;
				}
				if (isPlanned && !ownerClan) {
					attackers++;
				}
				// find how many battles
				const battles = (attackers !== 0) ? Math.ceil(Math.log2(attackers)) + 1 : 0;
				// modify cells
				battleRow.children[1].textContent = sf.cw.mapFix(data.arena_name);
				battleRow.children[2].textContent = `${primeTime[0]}:${primeTime[1]}`;
				battleRow.children[2].dataset.sort = `${primeTime[0]}${primeTime[1]}`;
				battleRow.children[3].firstElementChild.textContent = data.province_revenue;
				battleRow.children[5].innerHTML = (data.owner) ? `<a target='_blank' href='https://eu.wargaming.net/clans/${data.owner.id}/'><span class='t-clantag' style='color: ${data.owner.color};'>[${data.owner.tag}]</span> <img src='${data.owner.emblem_url}'></a>` : "No Owner";
				if (data.owner && bs.cw.tier !== "Ɵ") {
					battleRow.children[5].appendChild(sf.elem("span", {
						className: "t-elo",
						innerHTML: `(${data.owner.elo_rating ? data.owner.elo_rating : data.owner[`elo_rating_${(bs.cw.event) ? bs.cw.tier : "10"}`]})`
					}));
				}
				if (isAuction) {
					//battleRow.children[8].textContent = `${primeTime[0]}:${primeTime[1]}:00`;
					//battleRow.children[8].dataset.sort = `${primeTime[0]}${primeTime[1]}.${battles}`;
				}
				// only continue if there are any attackers
				if (attackers) {
					const emptyCells = ((primeTime[2] - bs.table.eu[0]) * 2) + bs.table.static,
					lastBattle = battles + emptyCells;
					battleRow.children[9].textContent = attackers;
					battleRow.children[10].textContent = battles;
					for (let _conc = 0, _cell = bs.table.static + 1; _cell < battleRow.childElementCount; _cell++) {
						const cell = battleRow.children[_cell];
						if (_cell > emptyCells && _cell <= lastBattle) {
							const timeClass = `.${cell.classList.item(1)}`,
							timePrevClass = `.${cell.previousElementSibling.classList.item(1)}`,
							primeTimeConc = `${Number(primeTime[0]+primeTime[1])+([0,30,100,130,200,230,300,330][_conc])}`;
							if (!bs.table.s.includes(timeClass) || !bs.table.s.includes(timePrevClass)) {
								bs.table.s.push(timePrevClass, timeClass);
								if (_cell == lastBattle) {
									bs.table.s.push(`${timePrevClass} + th`, `${timePrevClass} + td`, `${timeClass} + th`, `${timeClass} + td`);
								}
							}
							if (ownerClan && _cell !== lastBattle) {
								cell.classList.add("t-noFight");
							}
							else {
								cell.classList.add("t-fight");
								if (isAuction) {
									cell.classList.add("t-auction");
								}
								if (!bs.dyn.prov.includes(data.province_id)) {
									if (bs.dyn.conc[primeTimeConc]) {
										bs.dyn.conc[primeTimeConc]++;
									}
									else {
										bs.dyn.conc[primeTimeConc] = 1;
									}
								}
							}
							if (_cell == lastBattle) {
								if (ownerClan) {
									cell.classList.add("js-last");
									let nextBattle = cell.dataset.time;
									if (primeTime[1] == 15) {
										time = nextBattle.match(/(\d+)/g);
										nextBattle = `${time[0]}:${parseFloat(time[1])+15}`;
									}
									//battleRow.children[8].textContent = `${nextBattle}:00`;
									//battleRow.children[8].dataset.sort = `${nextBattle.replace(":","")}`;
								}
								if (bs.cw.globalmap && (!data.owner || !data.owner.division_id) || battleRow.children[6].firstElementChild.innerHTML == "No Division") {
									cell.classList.add("t-noOwner");
									if (bs.dyn.conc[primeTimeConc]) {
										bs.dyn.conc[primeTimeConc]--;
									}
								}
								cell.innerHTML = "♖";
								cellOwnerTime = [parseFloat(cell.classList.item(1).match(/\d+/g)[0]), parseFloat(cell.classList.item(1).match(/\d+/g)[1])];
								if (cellOwnerTime[0] < 5) {
									cellOwnerTime[0] += 24;
								}
							}
							else {
								cell.innerHTML = "&#9876;";
							}
							if (primeTime[1] == "15") {
								battleRow.classList.add("timeShift");
								cell.innerHTML += "<span class='t-timeShift'>+</span>";
							}
							_conc++;
						}
					}
					if (!bs.dyn.prov.includes(data.province_id)) {
						bs.dyn.prov.push(data.province_id);
					}
					if (bs.dyn.check >= bs.cw.bats + bs.dyn.plan) {
						sf.cw.handlerFooter("tourney", data.province_id);
					}
					// check if battle is planned or not started and change state to ongoing
					if (!/\[|Free Round/i.test(battleRow.children[7].textContent) && new Date().getHours() >= primeTime[0] - 1 && new Date().getHours() < cellOwnerTime[0]) {
						switch (battleRow.children[6].firstElementChild.innerHTML) {
							case ("Attack"):
								battleRow.children[7].textContent = battleResult; //"Ongoing";
								break;
							case ("Planned"):
								battleRow.children[6].firstElementChild.textContent = "Defense";
								battleRow.children[7].textContent = "Ongoing";
								break;
							case ("Defense"):
								battleRow.children[7].textContent = "Ongoing";
								sf.request({name: "provData", api: bs.api.prov + data.province_id, handler: sf.cw.handlerProv, mode: "cw", province: data.province_id});
								break;
							default:
								break;
						}
					}
					else if (battleRow.children[7].innerHTML == "Planned" && bs.time.r[0] > cellOwnerTime[0]) {
						battleRow.children[7].textContent = "Completed";
					}
				}
				else {
					const lastBattle = battleRow.getElementsByClassName(`t-${primeTime[0]}_00`)[0];
					if (primeTime[1] == "15") {
						battleRow.classList.add("timeShift");
						lastBattle.innerHTML = "♖<span class='t-timeShift'>+</span>";
					}
					else {
						lastBattle.innerHTML = "♖";
					}
					lastBattle.classList.add("t-noFight");
				}
				if (ownerClan) {
					bs.dyn.gold += data.province_revenue;
					document.getElementById('js-gold').textContent = bs.dyn.gold; // insert gold count
				}
				if (bs.cw.gold && data.province_revenue === 0) {
					document.getElementById('js-goldInfo').textContent = "(No Gold Revenue in Event!)";
					bs.cw.gold = false;
					style.textContent += "th.t-gold, td.t-gold {display: none;}";
				}
				// refresh table
				sortTable.refresh();
			},
			handlerProvs(data) {
				// clan provinces handler
				const provs = data.data[bs.clan.id],
				ownedProvinces = [],
				provTimes = [],
				provFragment = document.createDocumentFragment();
				if (battleTable.rows[1] && battleTable.rows[1].classList.contains("t-cwText")) {
					battleTable.children[1].innerHTML = ""; // empty table
				}
				if (provs) {
					for (let _p = 0, _p_len = provs.length; _p < _p_len; _p++) {
						const prov = provs[_p],
						battleRow = document.getElementsByClassName(prov.province_id)[0];
						if (!battleRow) {
							const primeTime = [sf.cw.time(parseFloat(prov.prime_time.match(/\d+/g)[0])), prov.prime_time.match(/\d+/g)[1], parseFloat(prov.prime_time.match(/\d+/g)[0]) + bs.table.eu.length],
							provRow = sf.elem("tr", {
								className: `province ${prov.province_id} defense`,
								innerHTML: `<td><a target='_blank' href='https://eu.wargaming.net/globalmap/#province/${prov.province_id}'>${prov.province_name}</a> [<a class='t-tournament' target='_blank' href='https://eu.wargaming.net/globalmap/#tournament/${prov.province_id}'>&#9876;</a>]</td><td>${sf.cw.mapFix(prov.arena_name)}</td><td data-sort='${primeTime[2]}${primeTime[1]}'>${primeTime[0]}:${primeTime[1]}</td><td class='t-gold'><span>${prov.daily_revenue}</span><span class='icon icon_main icon_gold'></span></td><td class='t-fame'>Ɵ</td><td><a target='_blank' href='https://eu.wargaming.net/clans/${bs.clan.id}/'><span class='t-clantag'>[${bs.clan.tag}]</span> <img src='${bs.clan.emblem}'></a><span class='t-elo'>(${bs.cw.elo[prov.max_vehicle_level]})</span></td><td><span>Defense</span><span></span></td><td>No Attacks</td><td class='t-nextBattle' data-sort='9999'></td><td class='t-battle' data-sort='99'>Ɵ</td><td class='t-battle t-border' data-sort='99'>Ɵ</td>${bs.table.c}`
							}),
							provTime = `t-${primeTime[0]}_00`,
							provTimeClass = `.${provTime}, .${provTime} + td, .${provTime} + th`,
							lastBattle = provRow.getElementsByClassName(provTime)[0];
							provRow.dataset.primeTime = JSON.stringify(primeTime);
							ownedProvinces.push(prov.province_id);
							bs.dyn.gold += prov.daily_revenue;
							bs.cw.tier = prov.max_vehicle_level;
							if (primeTime[1] == "15") {
								provRow.classList.add("timeShift");
								lastBattle.innerHTML = "♖<span class='t-timeShift'>+</span>";
							}
							else {
								lastBattle.innerHTML = "♖";
							}
							lastBattle.classList.add("t-noFight");
							if (!provTimes.includes(provTimeClass)) {
								provTimes.push(provTimeClass);
							}
							if (bs.cw.gold && prov.daily_revenue === 0) {
								document.getElementById('js-goldInfo').textContent = "(No Gold Revenue in Event!)";
								bs.cw.gold = false;
								style.textContent += "th.t-gold, td.t-gold {display: none;}";
							}
							// get province famepoints if event
							if (bs.cw.event) {
								sf.request({name: "provData", api: bs.api.prov + prov.province_id, handler: sf.cw.handlerProv, mode: "cw", province: prov.province_id});
							}
							provFragment.appendChild(provRow);
						}
					}
					// display finals column
					styleDynFinales.textContent += `${provTimes.join(", ")} {display: table-cell !important;}`;
					// insert province count
					document.getElementById('js-provs').textContent = provs.length;
					// insert gold count
					document.getElementById('js-gold').textContent = bs.dyn.gold;
					// send request for raids if event
					//if (bs.cw.event) {
					//  sf.request({name: "raidsData", api: bs.api.raids, handler: sf.cw.handlerRaids, mode: "cw"});
					//}
				}
				else if (bs.cw.bats === 0) {
					battleTable.children[1].innerHTML = ""; // empty table
					provFragment.appendChild(sf.elem("tr", {
						className: "t-cwText",
						innerHTML: "<td colspan='23'>No Battles</td>"
					}));
				}
				battleTable.children[1].appendChild(provFragment);
				// send request for divisions
				sf.request({name: "divsData", api: bs.api.divs, handler: sf.cw.handlerDivs, mode: "cw"});
				// refresh table
				sortTable.refresh();
			},
			handlerProv({province, owner}, coef) {
				// province info handler
				const battleRow = document.getElementsByClassName(province.alias)[0];
				let fame_style = "t-green",
				fame = "Ɵ",
				sort = 0;
				if (bs.cw.event) {
					if (province.fame_points) {
						fame = province.fame_points;
						sort = fame;
					}
					else if (province.money_box) {
						if (owner.id == bs.clan.id) {
							fame_style = "t-red";
							fame = -Math.abs(province.money_box.risky_fame_points);
						}
						else {
							fame = `+${province.money_box.capture_fame_points}`;
						}
						sort = fame;
					}
					else if (province.is_enclave) {
						fame = province.single_province_fp;
						coef = province.fame_points_coefficient;
						sort = fame;
					}
					else if (province.enclave_neighbours_number) {
						fame = `${province.enclave_neighbours_number}/${province.number_of_enclave_provinces}`;
						sort = province.enclave_neighbours_number / province.number_of_enclave_provinces;
						// change fame column title
						document.getElementById('js-fame').textContent = "Fame & Enclaves";
					}
					else if (province.raids) {
						if (province.raids.secondary_mission_reward) {
							fame = province.raids.secondary_mission_reward;
						}
						else {
							fame_style = "";
						}
					}
					if (province.type !== "landing" || (owner && owner.id == bs.clan.id)) {
						coef = "x5";
					}
				}
				if (battleRow) {
					const fameHTML = `<span class='${fame_style}'>${fame}</span>${(coef) ? ` ${coef}` : ""}`,
					battleFront = province.front_id.match(/league\d/)[0];
					battleRow.children[4].innerHTML = fameHTML;
					battleRow.children[4].dataset.sort = sort;
					if (bs.front_loc[battleFront]) {
						battleRow.children[6].lastElementChild.innerHTML = bs.front_loc[battleFront];
					}
					if (province.type == "auction") {
						if (battleRow.children[7].innerHTML == "Not Started") {
							battleTable.children[1].appendChild(sf.elem("tr", {
								className: `battle ${province.alias} attack auction`,
								innerHTML: `<td><a target='_blank' href='https://eu.wargaming.net/globalmap/#province/${province.alias}'>${province.name}</a> [<a class='t-tournament' target='_blank' href='https://eu.wargaming.net/globalmap/#tournament/${province.alias}'>&#9876;</a>]</td><td></td><td></td><td class='t-gold'><span></span><span class='icon icon_main icon_gold'></span></td><td class='t-fame'>${fameHTML}</td><td></td><td class='t-auction'><span>Auction</span><span>${bs.front_loc[battleFront] ? bs.front_loc[battleFront] : ""}</span></td><td>Not Started</td><td class='t-nextBattle' data-sort='9999'></td><td class='t-battle'>Ɵ</td><td class='t-battle t-border'>Ɵ</td>${bs.table.c}`
							}));
							battleRow.remove();
							// request tourneyData to be sure of proper visuals
							sf.request({name: "tourneyData (auction)", api: `${bs.api.tourney+province.alias}&round=1`, handler: sf.cw.handlerTourney, mode: "cw", province: province.alias});
						}
						else {
							battleRow.classList.add("auction");
							battleRow.children[6].classList.add("t-auction");
							battleRow.children[6].firstElementChild.textContent = "Auction";
						}
					}
				}
			},
			handlerDivs(data) {
				// divisions handler
				const divsId = JSON.stringify(data).match(/\d{9}/g);
				if (divsId.includes(bs.clan.id.toString())) {
					bs.cw.globalmap = true;
					for (let _p = 0, _p_len = data.data.length; _p < _p_len; _p++) {
						const div = data.data[_p],
						battleRow = document.getElementsByClassName(div.alias)[0];
						if (!div.division) {
							if (battleRow && battleRow.classList.contains('defense')) {
								const defBattle = battleRow.getElementsByClassName("js-last")[0],
								primeTime = JSON.parse(battleRow.dataset.primeTime),
								primeTimeConc = `${Number(primeTime[0]+primeTime[1])+([0,30,100,130,200,230,300,330][Number(battleRow.children[10].innerHTML) || 0])}`;
								battleRow.children[2].dataset.sort = 5000;
								battleRow.children[8].dataset.sort = 5000;
								battleRow.children[6].firstElementChild.textContent = "No Division";
								battleRow.children[6].classList.add("t-bold");
								if (defBattle) {
									defBattle.classList.remove("t-fight");
									defBattle.classList.add("t-noFight");
									if (bs.dyn.conc[primeTimeConc]) {
										bs.dyn.conc[primeTimeConc]--;
									}
								}
							}
							else if (!battleRow) {
								bs.dyn.plan++;
								battleTable.children[1].appendChild(sf.elem("tr", {
									className: `planned ${div.alias}`,
									innerHTML: `<td><a target='_blank' href='https://eu.wargaming.net/globalmap/#province/${div.alias}'>${div.name}</a> [<a class='t-tournament' target='_blank' href='https://eu.wargaming.net/globalmap/#tournament/${div.alias}'>&#9876;</a>]</td><td></td><td></td><td class='t-gold'><span></span><span class='icon icon_main icon_gold'></span></td><td class='t-fame'>Ɵ</td><td></td><td><span>Planned</span><span></span></td><td>Planned</td><td class='t-nextBattle' data-sort='9999'></td><td class='t-battle'>Ɵ</td><td class='t-battle t-border'>Ɵ</td>${bs.table.c}`
								}));
								sf.request({name: "batsData", api: bs.api.bats + div.alias, handler: sf.cw.handlerBats, mode: "cw", extra: true, province: div.alias});
							}
						}
						else {
							// sometimes future defenses wont show up in planned battles
							if (div.attackers.length > 0 && battleRow && battleRow.classList.contains('province')) {
								bs.dyn.plan++;
								battleTable.children[1].appendChild(sf.elem("tr", {
									className: `planned ${div.alias}`,
									innerHTML: `<td><a target='_blank' href='https://eu.wargaming.net/globalmap/#province/${div.alias}'>${div.name}</a> [<a class='t-tournament' target='_blank' href='https://eu.wargaming.net/globalmap/#tournament/${div.alias}'>&#9876;</a>]</td><td></td><td></td><td class='t-gold'><span></span><span class='icon icon_main icon_gold'></span></td><td class='t-fame'>Ɵ</td><td></td><td><span>Defense</span><span></span></td><td>Planned</td><td class='t-nextBattle' data-sort='9999'></td><td class='t-battle'>Ɵ</td><td class='t-battle t-border'>Ɵ</td>${bs.table.c}`
								}));
								battleRow.remove();
								sf.request({name: "tourneyData", api: `${bs.api.tourney+div.alias}&round=1`, handler: sf.cw.handlerTourney, mode: "cw", extra: true, province: div.alias});
							}
						}
						// update footer
						if (bs.dyn.check >= bs.cw.bats + bs.dyn.plan) {
							sf.cw.handlerFooter("divisions", div.alias);
						}
					}
					if (bs.dyn.plan > 0) {
						// style.textContent += ".t-battle {display: table-cell !important;}";
					}
					// refresh table
					sortTable.refresh();
				}
				else {
					document.getElementById('js-error').textContent = "Division Data not Available!";
				}
			},
			handlerFreepass(data) {
				const battleRow = document.getElementsByClassName(data.province_id)[0],
				lastGroup = data.battles[data.battles.length - 1],
				freeRound = battleRow.children[7].innerHTML == "Not Started" && lastGroup && lastGroup.is_fake && lastGroup.first_competitor.id == bs.clan.id;
				//console.log(data.province_id, lastGroup);
				// check if no opponent - free round
				if (freeRound) {
					battleRow.children[7].textContent = "Free Round";
					battleRow.children[7].classList.add("t-bold");
					battleRow.classList.add("freePass");
				}
			},
			handlerFooter(mode, province) {
				const footer = document.getElementById('js-footer'),
				conc = Object.entries(bs.dyn.conc).reduce(function(max, arr) {
					return max[1] >= arr[1] ? max : arr;
				}),
				conc_table = {};
				document.getElementById('js-battlesConc').textContent = `${conc[1]} [${conc[0].replace(/^(\d{2})/,"$1:")}]`;
				styleDynBattles.textContent = `${bs.table.s.join(", ")} {display: table-cell !important;}`;
				for (let _c_k = Object.keys(bs.dyn.conc), _c = _c_k.length; _c > 0; _c--) {
					const key = _c_k[_c - 1],
					hour = key.slice(0, 2),
					min = key.slice(2),
					newKey = `t-${hour >= 24 ? hour-24 : hour}_${min == 15 ? "00" : (min == 45 ? "30" : min)}`,
					time = bs.dyn.conc[key],
					timeShift = /15|45/.test(min) ? true : false;
					if (conc_table[newKey]) {
						conc_table[newKey][timeShift ? 1 : 0] += time;
					}
					else {
						conc_table[newKey] = timeShift ? [0, time] : [time, 0];
					}
				}
				for (let _ct_k = Object.keys(conc_table), _ct = _ct_k.length; _ct > 0; _ct--) {
					const key = _ct_k[_ct - 1],
					times = conc_table[key],
					foot = footer.getElementsByClassName(key)[0];
					if (foot) {
						foot.textContent = `${times[0] ? times[0] : ""}${times[1] ? ` +${times[1]}` : ""}`;
					}
					else {
						console.error("Foot doesn't exist", key, times);
					}
				}
			},
			handlerRaids(data) {
				// raids handler for campaign events
				for (let _r = 0, _r_len = data.length; _r < _r_len; _r++) {
					const raid = data[_r],
					battleRow = document.getElementsByClassName(raid.province.id)[0],
					fame = raid.fame_points,
					bonus = raid.bonus_fame_points,
					sort = fame + bonus,
					coef = raid.battle_coef;
					let denyFame = 0;
					if (battleRow) {
						denyFame = parseFloat(battleRow.children[4].innerHTML.match(/\d+/));
						battleRow.children[4].innerHTML = `<span>${fame} + ${bonus}${(denyFame) ? ` + ${denyFame}` : ""}</span> ${coef}`;
						battleRow.children[4].dataset.sort = sort + denyFame;
					}
				}
			},
			handlerError(name, data) {
				// error handler
				switch (name) {
					case ("mainData"):
						battleTable.children[1].appendChild(sf.elem("tr", {
							className: "t-cwText",
							innerHTML: "<td colspan='23'>Clan ID Error</td>"
						}));
						inputSpan.lastElementChild.textContent = "Clan ID invalid!";
						localStorage.removeItem("battles_clanid");
						break;
					case ("divsData"):
						document.getElementById('js-error').textContent = "Division Data not Available!";
						break;
					default:
						break;
				}
			},
			time(hour, min, type) {
				// time converter
				let time = hour + bs.time.o;
				if (time >= 24) {
					time -= 24;
				}
				else if (time <= 0) {
					time += 24;
				}
				if (type == "s") {
					time = `t-${time}_${min}${(time === 0 && min == "00") ? " t-24_00" : ""}`;
				}
				return time;
			},
			timer() {
				// timestamp handler
				const dateNow = new Date(),
					time = {
						h: sf.cw.time(16) - dateNow.getHours(),
						m: 60 - dateNow.getMinutes() - 1,
						s: 60 - dateNow.getSeconds() - 1
					},
					timeSpan = document.getElementById('js-timePrime');
				if (timeJump && !bs.cw.event && bs.cw.status) {
					timeSpan.textContent = "No Event Running";
					timeSpan.classList.add("t-bold");
					clearInterval(timeInterval);
				}
				else if (time.h >= 0 && (time.s > 0 || time.m < 15)) {
					timeSpan.textContent = `${((time.h > 0) ? `${time.h} Hours, ` : "")+((time.m > 0) ? `${time.m} Mins, ` : "")+time.s} Secs`;
				}
				else if (time.h < 0 && bs.cw.bats !== "Ɵ") {
					if (bs.cw.bats === 0) {
						timeSpan.textContent = "No Planned Battles";
						timeSpan.classList.add("t-bold");
						clearInterval(timeInterval);
					}
					else {
						timeSpan.classList.add("h-shadow");
						timeSpan.innerHTML = "<span style='color:#ff0000;'>X</span><span style='color:#ff2a00;'></span><span style='color:#ff5500;'>e</span><span style='color:#ff7f00;'></span><span style='color:#ffaa00;'>n</span> <span style='color:#ffff00;'>i</span><span style='color:#aaff00;'></span><span style='color:#55ff00;'>s</span> <span style='color:#00ff80;'>a</span> <span style='color:#00aaff;'>f</span><span style='color:#0055ff;'></span><span style='color:#0000ff;'>g</span><span style='color:#2e00ff;'></span><span style='color:#5d00ff;'>t</span><span style='color:#8b00ff;'>.</span>";
						if (bs.cw.current > 0) {
							document.getElementById('js-provStatus').textContent = "Next Opponent (ELO)";
						}
						clearInterval(timeInterval);
					}
				}
				else {
					timeSpan.textContent = "Hold on a sec...";
				}
				timeJump = true;
			},
			mapFix(name) {
				// map name fixer
				const fixedNames = {
					"114_czech/name": "Pilsen",
					"99_poland/name": "Studzianki"
				};
				return (fixedNames[name]) ? fixedNames[name] : name;
			},
			updater(force) {
				// updater handler
				const dateNow = new Date(),
					newDate = {
						h: dateNow.getHours(),
						m: dateNow.getMinutes(),
						o: (dateNow.getTimezoneOffset() > 0 ? -Math.abs(dateNow.getTimezoneOffset()) : Math.abs(dateNow.getTimezoneOffset())) / 60
					},
					newTime = ((bs.time.m >= 15 && bs.time.m <= 45) ? [bs.time.h, "30"] : ((bs.time.m <= 15) ? [bs.time.h, "00"] : [(bs.time.h + 1), "00"]));
				if (force || (bs.time.r[0] !== newTime[0] || bs.time.r[1] !== newTime[1])) {
					bs.time = newDate;
					bs.time.r = newTime;
					bs.time.t = `${bs.time.r[0]}_${bs.time.r[1]}`;
					battleTable.lastElementChild.firstElementChild.innerHTML = `<td></td><td></td><td></td><td class='t-gold'></td><td></td><td></td><td></td><td></td><td></td><td></td><td class='t-border'></td>${bs.table.c}`;
					styleDynTimezone.textContent = `
						.b-battles .b-battles-holder .t-battles tr .t-${bs.time.t} {background-color: rgba(254,252,223, 0.5); border-left: 1px solid #808080; border-right: 1px solid #808080;}
						.b-battles .b-battles-holder .t-battles tr .t-${bs.time.t} + th, .b-battles .b-battles-holder .t-battles tr .t-${bs.time.t} + td {background-color: rgba(224,223,218, 0.5); border-right: 1px solid #808080;}
					`;
					bs.dyn = {
						conc: {},
						prov: [],
						plan: 0,
						check: 0,
						gold: 0
					};
					sf.request({name: "mainData", api: bs.api.clan, handler: sf.cw.handlerMain, mode: "cw"});
					// insert update timestamp
					document.getElementById('js-batttleUpdate').textContent = new Date().toLocaleTimeString("en-GB");
				}
			}
		},
		request({name, api, handler, mode, extra, province = ""}) {
			// request handler
			GM.xmlHttpRequest({
				method: "GET",
				url: api,
				headers: {
					"Accept": "application/json",
					"Client-ID": mode == "tw" ? bs.tw.key : undefined
				},
				onload(resp) {
					const data = JSON.parse(resp.responseText);
					if (resp.status == 200) {
						if (bs.debug) {
							console.info(`${name}${province ? ": province" : ""}`, {data, api, "time": new Date().toLocaleTimeString("en-GB")});
						}
						handler(data, extra);
					}
					else {
						console.error("Error with API", name, api, resp);
						sf[mode].handlerError(name);
					}
				},
				onerror(resp) {
					console.error("Error accessing API", name, api, resp);
				}
			});
		}
	};
	// inserting style into head
	style = sf.elem("style", {
		className: "idealScript",
		type: "text/css",
		textContent: `
/* scipt buttons */
.b-scriptButton {height: 25.2px}
.b-scriptButton a {vertical-align: middle;}
.t-fakeButton {cursor: pointer; border-radius: 5px; padding: 2px 5px; transition: 0.3s;}
.t-fakeButton:hover {background-color: rgba(57, 51, 49, 0.15);}
/* icon rules */
.b-idealscript .icon {display: inline-block; height: 16px; width: 16px; vertical-align: text-top;}
.b-idealscript.b-scriptButton .icon {display: inline-block; height: 16px; width: 16px; margin-right: 3px; vertical-align: sub;}
.icon_main {background: url(${img.main}) no-repeat 0 0;}
.b-idealscript .icon_chat {}
.b-idealscript .icon_twitch {background-position: -16px 0;}
.b-idealscript .icon_fork {background-position: -32px 0;}
.b-idealscript .icon_wg {background: url(${img.main}) no-repeat -48px 0;}
.b-idealscript .icon_cw {background-position: -64px 0;}
.b-idealscript .icon_gold {background-position: -82px 0; margin-left: 2px;}
.b-idealscript .icon_wot {background-position: -98px 0;}
/* battle scheduler */
.b-battles {background-color: #D1E8FE; border: 1px solid; border-radius: 10px; display: table; font-size: 11px; width: 90vw; min-width: 1280px; margin: 25px auto 50px;}
.b-battles .h-battles {}
.b-battles .h-battles .h-battles-info {border-bottom: 1px solid #F5F5F5; margin: 0 auto; padding: 4px 0px; width: 98%; display: flex; align-items: center; justify-content: space-between;}
.b-battles .h-battles .h-battles-info .h-left {width: 350px;}
.b-battles .h-battles .h-battles-info .h-left a {font-size: 13px;}
.b-battles .h-battles .h-battles-info .h-mid {text-align: center;}
.b-battles .h-battles .h-battles-info .h-mid #js-eventName {text-transform: capitalize;}
.b-battles .h-battles .h-battles-info .h-right {text-align: right; width: 350px;}
.b-battles .h-battles .h-battles-info .h-right .h-expand {cursor: pointer; font-size: 2em; line-height: 10px; vertical-align: sub;}
.b-battles .h-battles .h-battles-info .h-right .h-force label {cursor: pointer;}
.b-battles .h-battles .h-battles-info .h-right .h-force input {height: 13px; vertical-align: bottom;}
.b-battles .h-battles .h-battles-info .h-right #js-update {margin-right: 17px;}
.b-battles .h-battles .h-battles-info img {max-height: 16px; vertical-align: bottom;}
.b-battles .h-battles .h-battles-info .h-shadow {font-weight: bold; text-shadow: 0px 0px 1px rgba(27,27,28, 1), 0px 0px 2px rgba(27,27,28, 1);}
.b-battles .b-battles-holder {max-height: 90vh; overflow-y: auto;}
.b-battles .b-battles-holder .t-battles {border-spacing: 0; text-align: center; width: 100%;}
.b-battles .b-battles-holder .t-battles .t-time {display: none; position: relative;}
.b-battles .b-battles-holder .t-battles .sort-up, .b-battles .b-battles-holder .t-battles .sort-down {color: #C600C6;}
.b-battles .b-battles-holder .t-battles thead th {border-bottom: 1px solid #808080; line-height: 20px;}
.b-battles .b-battles-holder .t-battles tbody tr:nth-child(even) {background-color: #FBFBFB;}
.b-battles .b-battles-holder .t-battles tbody tr:nth-child(odd) {background-color: #EFEFEF;}
.b-battles .b-battles-holder .t-battles tbody tr:hover {background-color: #FEFAC0;}
.b-battles .b-battles-holder .t-battles tbody .t-tournament {font-size: 15px; font-weight: bold;}
.b-battles .b-battles-holder .t-battles tbody td {line-height: 19px; border-bottom: 1px dotted #B1B1B1;}
.b-battles .b-battles-holder .t-battles tbody td:first-of-type {max-width: 100px; overflow: hidden; padding: 0 5px; text-overflow: ellipsis; white-space: nowrap;}
.b-battles .b-battles-holder .t-battles tbody .t-title {font-weight: bold;}
.b-battles .b-battles-holder .t-battles tbody .t-good {color: #4D7326;}
.b-battles .b-battles-holder .t-battles tbody .t-bad {color: #930D0D;}
.b-battles .b-battles-holder .t-battles tbody .t-plan {color: #FFE400;}
.b-battles .b-battles-holder .t-battles tbody .t-fight {color: #4D7326; font-size: 15px; font-weight: bold;}
.b-battles .b-battles-holder .t-battles tbody .t-auction {color: #2F396A; font-weight: bold;}
.b-battles .b-battles-holder .t-battles tbody .t-noFight {color: #808080; font-size: 14px;}
.b-battles .b-battles-holder .t-battles tbody .t-fight.t-noOwner {color: #808080;}
.b-battles .b-battles-holder .t-battles tbody .t-error {color: #CD2911;}
.b-battles .b-battles-holder .t-battles tbody .t-cwText td {font-size: 26px; line-height: 54px;}
.b-battles .b-battles-holder .t-battles tbody .timeShift td:nth-child(3), .b-battles .b-battles-holder .t-battles tr.timeShift td:nth-child(9) {color: #25931A;}
.b-battles .b-battles-holder .t-battles tbody .timeShift td .t-timeShift {font-size: 8px; position: absolute;}
.b-battles .b-battles-holder .t-battles tbody img {height: 16px; margin-bottom: 2px; vertical-align: bottom;}
.b-battles .b-battles-holder .t-battles tfoot td {border-top: 1px solid #808080; font-weight: bold; line-height: 20px;}
.b-battles .b-battles-holder .t-battles tr .t-border {border-right: 2px solid rgba(194, 173, 173, 0.5);}
.b-battles .f-battles {}
.b-battles .f-battles .f-battles-info {border-top: 1px solid #F5F5F5; margin: 0 auto; padding: 3px 0px; width: 98%; display: flex; align-items: center; justify-content: space-between;}
.b-battles .f-battles .f-battles-info .f-left {width: 350px;}
.b-battles .f-battles .f-battles-info .f-left .f-input > span {margin-left: 5px;}
.b-battles .f-battles .f-battles-info .f-left .f-inputText {color: #CD2911;}
.b-battles .f-battles .f-battles-info .f-left .f-inputText.t-green {color: #4D7326;}
.b-battles .f-battles .f-battles-info .f-mid {text-align: center;}
.b-battles .f-battles .f-battles-info .f-mid-tables {display: flex;}
.b-battles .f-battles .f-battles-info .f-mid table {margin: 0 auto;}
.b-battles .f-battles .f-battles-info .f-mid table td {padding: 0 10px;}
.b-battles .f-battles .f-battles-info .f-mid #js-goldInfo {margin-left: 3px;}
.b-battles .f-battles .f-battles-info .f-mid #js-error {display: block; color: #CD2911;}
.b-battles .f-battles .f-battles-info .f-right {text-align: right; width: 350px;}
.b-battles .f-battles .f-battles-info img {max-height: 16px; vertical-align: bottom;}
/* toggle overrides */
.t-elo {margin-left: 3px;}
.t-gold {color: #AC813C;}
.b-display-none {display: none;}
.b-display-block {display: block;}
/* .t-battle {display: none;} */
.t-bold {font-weight: bold;}
.t-green {color: #4D7326;}
.t-red {color: #930D0D;}
	`
	});
	document.head.appendChild(style);
	// link to battle scheduler
	const rightSide = document.getElementsByClassName("linklist rightside")[0];
	rightSide.prepend(sf.elem("li", {
		className: "b-idealscript b-scriptButton",
		innerHTML: `<a target='_blank' href='./games.php'><span class="icon icon_main icon_cw"></span>Battle Schedule</a>`
	}));
	rightSide.prepend(sf.elem("li", {
		className: "b-idealscript b-scriptButton",
		innerHTML: `<a target='_blank' href='https://eu.wargaming.net/clans/wot/500010805/'><span class="icon icon_main icon_wg"></span>Clan Page</a>`
	}));
	if (/games.php/.test(window.location.href)) {
		styleDynTimezone = sf.elem("style", {
			className: "styleDynTimezone",
			type: "text/css",
			textContent: `
				.b-battles .b-battles-holder .t-battles tr .t-${bs.time.t} {background-color: rgba(254,252,223, 0.5); border-left: 1px solid #808080; border-right: 1px solid #808080;}
				.b-battles .b-battles-holder .t-battles tr .t-${bs.time.t} + th, .b-battles .b-battles-holder .t-battles tr .t-${bs.time.t} + td {background-color: rgba(224,223,218, 0.5); border-right: 1px solid #808080;}
			`
		});
		styleDynBattles = sf.elem("style", {
			className: "styleDynBattles",
			type: "text/css"
		});
		styleDynFinales = sf.elem("style", {
			className: "styleDynFinales",
			type: "text/css"
		});
		document.head.appendChild(styleDynTimezone);
		document.head.appendChild(styleDynBattles);
		document.head.appendChild(styleDynFinales);
		// prepare static html
		const page_body = document.getElementById("page-body"),
		chat = page_body.getElementsByClassName("tablebg")[0],
		battlePanel = sf.elem("div", {
			className: "b-idealscript b-battles",
			innerHTML: `<div class='h-battles'><div class='h-battles-info'><div class='h-left'><a class="t-fakeButton" target='_blank' href='https://greasyfork.org/en/scripts/20094-ideal-scripts' title='Script Page'><span class='icon icon_main icon_fork'></span></a><a class="t-fakeButton" target='_blank' href='https://eu.wargaming.net/clans/wot/${bs.clan.id}/globalmap' title='Clan Page'><span class='icon icon_main icon_wg'></span></a><a class="t-fakeButton" target='_blank' href='https://eu.wargaming.net/globalmap/' title='Global Map'><span class='icon icon_main icon_cw'></span></a></div><div class='h-mid'><span id='js-eventName'></span><span id='js-clan'></span><span id='js-timePrime'>Ɵ</span></div><div class='h-right'><span class='t-fakeButton' id='js-update'>Update</span><span class='h-force t-fakeButton' id='js-force'><label>Campaign Only: <input type='checkbox' name='force'></label></span></div></div></div><div class='b-battles-holder'><table class='t-battles sortable'><thead><tr><th>Province</th><th>Map</th><th data-sort-method='number' data-sort-order='desc'>Timezone</th><th class='t-gold'>Gold</th><th class='t-fame' id='js-fame'>Fame</th><th>Owner (ELO)</th><th>Type</th><th id='js-provStatus'>Status</th><th class='t-battle sort-default'  data-sort-method='number' data-sort-order='desc'>Next Battle</th><th class='t-battle'>Attackers</th><th class='t-battle t-border'>Turns</th></tr></thead><tbody></tbody><tfoot id='js-footer'><tr><td></td><td></td><td></td><td class='t-gold'></td><td></td><td></td><td></td><td></td><td></td><td></td><td class='t-border'></td></tr></tfoot></table></div><div class='f-battles'><div class='f-battles-info'><div class='f-left'><div class='f-input' id='js-input'><input type='text' name='id' placeholder='Clan ID' value='${bs.clan.id}' list='clanid' maxlength='9' size='9'><datalist id='clanid'>${clans.join("")}</datalist><span class='f-inputImage'><img src='https://wot-life.com/img/clanicon/${bs.clan.id}.png'></span><span class='f-inputText'>${(bs.clan.id !== bs.clan.ideal) ? "<span class='f-inputBack'>Back to <a target='_blank' href='#' onclick='localStorage.removeItem(\"battles_clanid\"); location.reload();'>[IDEAL]</a></span>" : ""}</span></div><table><tr><td colspan='3'>Gold Income: <span class='t-gold' id='js-gold'>0</span><span class='icon icon_main icon_gold'></span><span id='js-goldInfo'></span></td></tr></table></div><div class='f-mid'><div id='js-tableStats' class='f-mid-tables b-display-none'><table><tr class='t-bold'><td>Current Battles: <span id='js-battles'>0</span></td><td>Simultaneously: <span id='js-battlesConc'>0</span></td></tr><tr><td>Planned: <span id='js-battlesPlan'>0</span></td><td>Owned Provinces: <span id='js-provs'>0</span></td></tr></table></div><span id='js-error'></span></div><div class='f-right'><div><span class='t-bold t-green'>&#9876;</span> Tournament Battle &#8226; <span class='t-bold t-green'>♖</span> Battle with Owner &#8226; <span class='t-bold t-green'>&#9876;+</span> Timeshift</div><div>Last Updated: <span id='js-batttleUpdate'>Ɵ</span> [UTC${(bs.time.o >= 0) ? "+" : ""}${bs.time.o}] &#8226; v${bs.vers}</span></div></div></div></div>`
		});
		page_body.parentNode.appendChild(chat);
		page_body.innerHTML = "";
		page_body.appendChild(battlePanel);
		page_body.appendChild(chat);
		// table references
		battleTable = battlePanel.children[1].firstElementChild;
		// time cells for header and body rows
		const timeFragment = document.createDocumentFragment();
		for (let _tc = 0, _tc_len = bs.table.eu.length; _tc < _tc_len; _tc++) {
			const t = bs.table.eu[_tc],
			times = [sf.cw.time(t, "00", "s"), `${sf.cw.time(t)}:00`, sf.cw.time(t, "30", "s"), `${sf.cw.time(t)}:30`];
			timeFragment.appendChild(sf.elem("th", {
				className: `t-time ${times[0]}`,
				innerHTML: times[1]
			}));
			bs.table.c += `<td class='t-time ${times[0]}' data-time='${times[1]}'></td>`;
			if (_tc !== _tc_len - 1) {
				timeFragment.appendChild(sf.elem("th", {
					className: `t-time ${times[2]}`,
					innerHTML: times[3]
				}));
				bs.table.c += `<td class='t-time ${times[2]}' data-time='${times[3]}'></td>`;
			}
		}
		battleTable.firstElementChild.firstElementChild.appendChild(timeFragment);
		battleTable.lastElementChild.firstElementChild.innerHTML += bs.table.c;
		// button to update
		const updateSpan = document.getElementById('js-update');
		updateSpan.addEventListener('click', function() {
			sf.cw.updater(true);
		}, false);
		// button to force load cw battles
		const forceSpan = document.getElementById('js-force');
		forceSpan.firstElementChild.lastElementChild.checked = (bs.cw.status) ? true : false;
		forceSpan.addEventListener('click', function() {
			localStorage.setItem("battles_force", this.firstElementChild.lastElementChild.checked);
			location.reload();
		}, false);
		// add custom input for checking other clans
		inputSpan = document.getElementById('js-input');
		inputSpan.firstElementChild.addEventListener('input', function() {
			const value = this.value;
			if (value.length == 9 && value[0] == "5") {
				inputSpan.children[2].firstElementChild.src = `https://wot-life.com/img/clanicon/${value}.png`;
				inputSpan.children[3].innerHTML = "Stored! <a href='' onclick='location.reload();'>Refresh?</a>";
				inputSpan.children[3].classList.add("t-green");
				if (inputSpan.children.length == 5) {
					inputSpan.children[4].textContent = "";
				}
				localStorage.setItem("battles_clanid", value);
			}
			else if (value.length > 0 && value[0] !== "5") {
				inputSpan.children[3].textContent = "Not Valid!";
			}
			else {
				inputSpan.children[3].textContent = "Missing";
			}
		}, false);
		// add intervals for time and round updater
		timeInterval = setInterval(sf.cw.timer, 1000); // 1 second
		updateInterval = setInterval(sf.cw.updater, 120000); // 2 minutes
		// activate tablesort function for battle scheduler
		if (Tablesort) {
			// Numeric sort
			Tablesort.extend('number', function(item) {
				return item.match(/^-?(\d)*-?([,\.]){0,1}-?(\d)+([E,e][\-+][\d]+)?%?$/); // Number
			}, function(a, b) {
				a = parseFloat(a);
				b = parseFloat(b);
				a = isNaN(a) ? 0 : a;
				b = isNaN(b) ? 0 : b;
				return a - b;
			});
			sortTable = new Tablesort(battleTable);
		}
		else {
			window.alert("Error activating tablesort, please refresh - if this shit continues, poke Orrie");
		}
		// insert update status - will crash the tablesorter if inserted earlier
		battleTable.children[1].appendChild(sf.elem("tr", {
			className: "t-cwText",
			innerHTML: "<td colspan='23'>Updating...</td>"
		}));
		// send request to wargaming api to see if an event is running
		sf.request({name: "eventData", api: bs.api.event, handler: sf.cw.handlerEvent, mode: "cw"});
	}
}(window));