WoTStatScript - Clanpage

More info for World of Tanks clan page.

Ajankohdalta 7.9.2015. Katso uusin versio.

// ==UserScript==
// @name        WoTStatScript - Clanpage
// @version     0.9.10.0.8
// @description More info for World of Tanks clan page.
// @author      Orrie
// @namespace   http://forum.worldoftanks.eu/index.php?/topic/263423-
// @icon        http://dl.dropboxusercontent.com/u/12497046/wot/projects/statscript/img/icon.png
// @include     http://*.wargaming.net/clans/*/*
// @grant       GM_xmlhttpRequest
// @license     MIT License
// ==/UserScript==
/*
	Changelogs:
	Profilepage: http://dl.dropboxusercontent.com/u/12497046/wot/projects/statscript/WoTStatScript-changelog.txt
	Clanpage: https://dl.dropboxusercontent.com/u/12497046/wot/projects/statscript/WoTStatScript-Clanpage-changelog.txt
*/
(function() {
	// global vars
	var d = document, c = d.cookie;

	// get server info and webpage
	var wg = {host:d.location.host, href:d.location.href, clan:{}};
	wg.srv = wg.host.match(/(eu|ru|na|com|asia|kr)/)[0].replace(/com/,"na");
	wg.m = /players\/wot/i.test(wg.href);

	// getting claninfo
	var emblemName = d.getElementsByClassName('page-header_emblem')[0],
	clanName = d.getElementsByClassName('clan_name')[0],
	sidebarName = d.getElementsByClassName('sidebar-clan_emblem')[0];
	wg.clan.id = wg.href.match(/\/(\d+)/)[1];
	wg.clan.name = (emblemName || clanName) ? ((clanName) ? clanName.firstElementChild.innerHTML.replace(/[\[\]]/g,"") : emblemName.alt) : sidebarName.alt;
	wg.p = new RegExp("\\["+wg.clan.name+"\\] \\|").test(d.title) && !/wowp/i.test(wg.href);

	// script variables
	var sc = {
		vers: "0.9.10.0.8",
		host: "http://greasyfork.org/en/scripts/12137-wotstatscript-clans",
		user: "http://forum.wotlabs.net/index.php?/user/1618-orrie/",
		top: {
			eu: "http://forum.worldoftanks.eu/index.php?showtopic=263423",
			na: "http://forum.worldoftanks.com/index.php?showtopic=404652"
		},
		api: {
			ru: "98ca7c4fb108175b67d6505b9c3f3ebd",
			eu: "a7595640a90bf2d19065f3f2683b171c",
			na: "bf5dba0efd444d75147b6222dd903fd2",
			asia: "95f8713eccd322e52dbf521dbd28b19c",
			kr: "ffea0f1c3c5f770db09357d94fe6abfb"
		},
		wn: "http://www.wnefficiency.net/exp/expected_tank_values_latest.json",
		loc: c.match(/wgccfe_language=(\w+)/)[1],
		locSup: ["en", "ru", "cz", "de", "fr", "pl", "es", "tr"]
	};
	// script threadlink
	sc.link = "<div class='b-scriptlink'><a target='_blank' href="+sc.host+">Script</a> version "+sc.vers+" - <a target='_blank' href="+((wg.srv == "na") ? sc.top.na : sc.top.eu)+">Thread</a></div>";

	// external site support
	var srv = {
		wl: false,    // wotlabs
		nm: false,    // noobmeter
		ws: false,    // wotstats
		cs: false,    // wotcs
		wlife: false, // wot-life
		as: false,    // away stats
		//wn: false,  // wot-numbers
		//tb: false,  // tomatobot
		ct: false,    // clan tools
		aos: false,   // age of strife
		kttc: false,  // kttc
		wots: false,  // wots
		ch: false,    // clan history
		wr: false     // wotreplays
	};

	// determine browser types
	var web = {
		gecko: typeof InstallTrigger !== 'undefined',
		opera: !!window.opera || /opera|opr/i.test(navigator.userAgent),
		chrome: !!window.chrome && !!window.chrome.webstore,
		safari: /constructor/i.test(window.HTMLElement)
	};

	// fetch wnefficiency values - check if array exists in localStorage, otherwise fetch and reload page
	var statObj = {},
	wnExpValues = JSON.parse(localStorage.getItem("wnExpValues")),
	wnExpDate = JSON.parse(localStorage.getItem("wnExpDate"))+12096e5 >= Date.now(), // true if timestamp is less than 2 weeks old, refresh list if false.
	wnExpVers = JSON.parse(localStorage.getItem("wnExpVers")) || "";
	if (wnExpVers[0]==sc.vers && wnExpValues && wnExpDate) {
		statObj = wnExpValues.data;
	}
	else {
		reqHnd(sc.wn, wnHnd, wnHnd_error);
	}

	// fetch stored clanlist stats - check if array exists in localStorage, otherwise tag fetching to true
	var s = {}, statFetch = false,
	ssValues = JSON.parse(localStorage.getItem("statScriptValues_"+wg.clan.id)),
	ssDate = JSON.parse(localStorage.getItem("statScriptDate_"+wg.clan.id))+6048e5 >= Date.now(); // true if timestamp is less than 1 weeks old, refresh list if false.
	if (ssValues && ssDate) {
		s = ssValues;
	}
	else {
		statFetch = true;
	}

	// inserting style into head
	var style = elem("style", "wotstatscript", "", "text/css");
	d.head.appendChild(style);

	// colour scale array
	var colArr = {
		//      col        wr  bat    sr  hr  dmg  wgr   wn8   wn7   eff   nm
		sUni: [ "#5A3175", 65, 30000, 50, 80, 300, 9900, 2900, 2050, 2050, 2000 ], // 99.99% super unicum
		uni:  [ "#83579D", 60, 25000, 46, 75, 270, 9000, 2450, 1850, 1800, 1950 ], // 99.90% unicum
		gr8:  [ "#3972C6", 56, 21000, 42, 70, 240, 8500, 2000, 1550, 1500, 1750 ], // 99.00% great
		vGud: [ "#4099BF", 54, 17000, 38, 65, 210, 6500, 1600, 1350             ], // 95.00% very good
		good: [ "#4D7326", 52, 13000, 34, 60, 180, 5000, 1200, 1100, 1200, 1450 ], // 82.00% good
		aAvg: [ "#849B24", 50, 10000, 30, 55, 150, 4000,  900                   ], // 63.00% above average
		avg:  [ "#CCB800", 48,  7000, 25, 50, 120, 3000,  650,  900,  900, 1250 ], // 40.00% average
		bAvg: [ "#CC7A00", 47,  3000, 20, 45,  90, 2000,  450,  700,  600, 1150 ], // 20.00% below average
		bas:  [ "#CD3333", 46,  1000, 15, 40,  60, 1500,  300,  500             ], //  6.00% basic
		beg:  [ "#930D0D",  0,     0,  0,  0,   0,    0,    0,    0,    0,    0 ], //  0.00% beginner
		dft:  [ "#6B6B6B" ], // default
		id: { "col": 0, "wr": 1, "bat": 2, "sr": 3, "hr": 4, "dmg": 5, "wgr": 6, "wn8": 7, "wn7": 8, "eff": 9, "nm": 10 }  // type identifier
	};

	// localization
	// cz-czech   - Crabtr33 and Ragnarocek
	// de-german  - ArtiOpa, Crakker and multimill
	// fr-french  - SuperPommeDeTerre
	// pl-polish  - KeluMocy and pokapokami
	// es-spanish - Frodo45127
	// tr-turkish - Ufuko
	// ru-russian - dimon222
	var loc = {
		// thousands separator
		sym: { en: ",", ru: " ", cz: " ", de: ".", fr: " ", pl: " ", es:".", tr: "."},
		// clan page
		c01: { en: "Clan Stats", ru: "Статистика клана", cz: "Stat. klanu", de: "Clanstatistiken", fr: "Statistiques du clan", pl: "Statystyki klanu", es: "Estadísticas del clan", tr: "Klan İstatistikleri" },
		c02: { en: "Replays:", ru: "Реплеи:", cz: "Záznamy:", de: "Replays", fr: "Replays:", pl: "Powtórki:", es: "Repeticiones:", tr: "Replayler" },
		// memberlist
		c03: { en: "Script Settings", ru: "Script Settings", cz: "Script Settings", de: "Script Settings", fr: "Script Settings", pl: "Script Settings", es:"Script Settings", tr: "Script Settings"},
		c04: { en: "Load Stats Automatically", ru: "Load Stats Automatically", cz: "Load Stats Automatically", de: "Load Stats Automatically", fr: "Load Stats Automatically", pl: "Load Stats Automatically", es:"Load Stats Automatically", tr: "Load Stats Automatically"},
		c05: { en: "Use Whitelist", ru: "Use Whitelist", cz: "Use Whitelist", de: "Use Whitelist", fr: "Use Whitelist", pl: "Use Whitelist", es:"Use Whitelist", tr: "Use Whitelist"},
		c06: { en: "Refresh WN8 Table", ru: "Refresh WN8 Table", cz: "Refresh WN8 Table", de: "Refresh WN8 Table", fr: "Refresh WN8 Table", pl: "Refresh WN8 Table", es: "Refresh WN8 Table", tr: "Refresh WN8 Table" },
		c07: { en: "Clean Script Database", ru: "Clean Script Database", cz: "Clean Script Database", de: "Clean Script Database", fr: "Clean Script Database", pl: "Clean Script Database", es: "Clean Script Database", tr: "Clean Script Database" },
		c08: { en: "Average Winrate", ru: "Average Winrate", cz: "Average Winrate", de: "Average Winrate", fr: "Average Winrate", pl: "Average Winrate", es:"Average Winrate", tr: "Average Winrate"},
		c09: { en: "Average WN8", ru: "Average WN8", cz: "Average WN8", de: "Average WN8", fr: "Average WN8", pl: "Average WN8", es:"Average WN8", tr: "Average WN8"}, // Average WN8
		c10: { en: "Fetch WN8 for Clan", ru: "Fetch WN8 for Clan", cz: "Fetch WN8 for Clan", de: "Fetch WN8 for Clan", fr: "Fetch WN8 for Clan", pl: "Fetch WN8 for Clan", es:"Fetch WN8 for Clan", tr: "Fetch WN8 for Clan"},
		c11: { en: "Fetching WN8 for Clan!", ru: "Fetching WN8 for Clan!", cz: "Fetching WN8 for Clan!", de: "Fetching WN8 for Clan!", fr: "Fetching WN8 for Clan!", pl: "Fetching WN8 for Clan!", es:"Fetching WN8 for Clan!", tr: "Fetching WN8 for Clan!"},
		c12: { en: "WN8 Fetched for Clan!", ru: "WN8 Fetched for Clan!", cz: "WN8 Fetched for Clan!", de: "WN8 Fetched for Clan!", fr: "WN8 Fetched for Clan!", pl: "WN8 Fetched for Clan!", es:"WN8 Fetched for Clan!", tr: "WN8 Fetched for Clan!"}
		//c00: { en: "", ru: "", cz: "", de: "", fr: "", pl: "", es:"", tr: ""},
	};

	// region settings for external sites
	switch(wg.srv) {
		case ("eu"): // eu server
			srv.wl = srv.nm = srv.ws = srv.cs = srv.wlife = srv.as = srv.wn = srv.tb = srv.ct = srv.kttc = srv.aos = srv.ch = srv.wr = wg.srv;
			break;
		case ("ru"): // ru server
			srv.wl = srv.nm = srv.wn = srv.ws = srv.cs = srv.tb = srv.ct = srv.kttc = srv.wots = srv.aos = srv.ch = srv.wr = wg.srv;
			break;
		case ("na"): // na server - american english
			srv.wl = srv.nm = srv.ws = srv.cs = srv.wlife = srv.wn = srv.tb = srv.ct = srv.kttc = srv.aos = srv.ch = wg.srv; srv.wr = "com"; srv.wn = "us";
			break;
		case ("asia"): // asia server
			srv.wl = srv.nm = srv.wn = srv.ws = srv.cs = "sea"; srv.ct = srv.kttc = srv.aos = srv.ch = wg.srv; srv.wr = "com";
			break;
		case ("kr"): // korean server
			srv.wl = srv.nm = srv.ws = srv.cs = srv.ct = srv.aos = srv.ch = wg.srv; srv.wr = "com";
			break;
		default: break;
	}

	// set script language to english if an unsupported language is detected
	if (sc.locSup.indexOf(sc.loc) == -1) {
		sc.loc = "en";
	}
	// process localization
	for (var _l in loc) {
		if (loc.hasOwnProperty(_l)) {
			loc[_l] = loc[_l][sc.loc];
		}
	}

	// add language to body classname for language based styling
	d.body.classList.add("lang-"+sc.loc);

	// variables for dropbox, css and data uri
	var css = {
		u: {
			cIcons: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAACACAMAAAA1SxkQAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAADeUExURUxpcTofR0GwyRsZGiIgHyYmJkqkxV1WazJn0f9qAECxyTyqwXAxlhsaGjNly0hTtRERER8dHEq0ynAxlvehhdrhhem/hSwqKhgXFUKwyBkXFEKxyTFlyzAoKHI1lHQron8axT+vxv+GhTJlzP+Chf+AhfR0Wdj9hUOxyf9sAZBKGvVhCv+BhX8axWJUZTFly6DqheicAP/nhf9rAPhrBf9/hfvxhf+phWFoIpNYHdU5LqNdenAxliQjI/9qACEXFjAiISkoKDgrKVBBN0UyMHlMR2tGQqWZlfn5+Xh0a6/IXu8AAAA8dFJOUwAYicrr9hMF/vZU+uiAhjUuqzGBEE4j1mqeVrO3nr1S+tCh04HDQcRvykLwX4b2V9f1s5+A233QvoXq0Fvc5mgAAANrSURBVEjHvZUJc6JMEIabQyaCKCCICGjUGHO4mjv59nM0HGLy///Q9swg6B5VW1tb25UM3c+83dMDIwD8mWny2DCcOnYwNHSw4tNY82PQOAgNQ9aA2IkFX1isY0xY7BM4HyEIDAOVcZKYMDpnEsMIAPpJwjLOzznABTD24QgwgXkAzCQ/8aWTXolE4B9aW4xR1G53Vm1mHJxxax9UUTTlIIrE/WmjD9G0045QtALgs+3VmbbinhBMp6tpxBRnUZlysLJu52B/bzvd1vpg/LZ2q3Dd5YJ6viXus/ArAeGg26kEQwQt7HBYCrprWA9Z7ZFYAi8glKQ1ZE8UawHPQC07Kpi4ZkWZz54tb4mvMhJHoFWBNc8armvQwiU6ot+y9SEpBa3D5rqjaoPl9vnY6n53b3reycki3t1d7xhgfOeBVzO3N/fmMJ/Xad7c9cCd15KXF5wkD15VVLgvL9WiD1zce0Wdx+a8B17Ofe3h/6sLMBHJZLKAxeTiAtxZWX4xcWeX7nPvclY20JstJgQumKhscPZ8eRiFXUyYdvHsVnvgHun9+shIfdsCYsZW9ZOkdICAqn2+rmQn1LYkybKpOmC1cMbs26of922qWBIQhdoDdbnfZw01oaoNlkobjeQz+/xMVJUqJtgULUmzfcYcWwKTXWn6uUw4IGApXJKlfAIXJgPMVJSlryjosN4kE0v1zT4uXXbGkhppA9c0xTuEWCaqsYWBVL1NrL5iDqxfvFNitXFkagwqPbIkUaFxHC+X/gnwh//fCJDwjaiDp+Y1B0mWsYt5ebtpcuC/vQ0Uqtxcb0pgPt0+3bz997gpAZtqXt/fN0uAtdDb3N9vOFBojLUqa8JNzHNrcP31a/MENG+PEjjYbE7BY/PEHn/vY/K9K9eAuY4mV58aJ9Ac/Ppo4zJJGzs4qcuBHnKihXog6yDLV8FVyH5JITqyDA5KnFAjBBNQgDWuglAPQQ4AL8EVS9ZlWdfCUGNX8aw1WZd1/JOd6nGTMSFj7bh7h3X4u69TSdnimRcjN2W73dJy5LZlVo7cVO6qNUCfVuNP7b02jMx3eE/TdJ+nAtg4pHmef+wzxO+gMppnWfaBJE9Tng5ZURQfSPI8BZSlUOx2O4yLLM8hZ3THwL4osiwHX4CiwBhBBlJcKnaMIsA+0h8a/QZnvrDP+ki71wAAAABJRU5ErkJggg==",
			arrow: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAECAMAAAB1GNVPAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAPUExURf///////////0xpcf///17pIXYAAAAEdFJOU393iAAiK7rGAAAAH0lEQVQI1w3GwQEAMBBEQBf6rzn7YeipxA0bXoU4LB8EgABGoTqNxwAAAABJRU5ErkJggg=="
		}
	};

	// style contents
	var styleClan = [
		// script header rules
		"#common_menu .cm-menu__user > *:not(.cm-notifications) {display: inline-block}",
		"#common_menu .b-scriptlink a {color: #E5B12E;}",
		"#common_menu .b-scriptlink a:hover {color: #FFBE4C; text-shadow: 0px 0px 7px rgba(255, 126, 0, 0.7);}",
		"#common_menu .b-login-msg:hover, #common_menu .b-scriptlink:hover {color: #707273; cursor: initial;}",
		"#common_menu .cm-link__get-gold {margin: 0 12px;}",
		".profile__main {margin: 0; padding: 0;}",
		// links menu rules
		".menu-clan_links {padding: 0;}",
		".menu-clan_links.cm-parent-link__opened {border: 1px solid #313335;}",
		".menu-clan_links .menu-top_link {cursor: pointer; padding: 0 8px 0 9px;}",
		".menu-clan_links .menu-top_link.cm-parent-link__opened {background: #0E0E0E; border-left: 1px solid #313335; border-right: 1px solid #313335; margin-left: -1px;}",
		".menu-clan_links .cm-arrow {background-image: url('"+css.u.arrow+"'); display: inline-block; margin-left: 5px; opacity: 0.5; vertical-align: middle; transition: opacity 0.2s ease 0s; height: 4px; width: 7px;}",
		".menu-clan_links .cm-parent-link__opened .cm-arrow {opacity: 1; transform: rotate(180deg);}",
		".menu-clan_links .clan-links {background: rgba(14, 14, 14, 0.99); border: 1px solid #313335; display: none; box-shadow: 0px 0px 25px rgba(0, 0, 0, 0.4); margin-left: -1px; padding: 14px 16px;}",
		".menu-clan_links .cm-sublist__opened {display: block;}",
		".menu-clan_links .clan-links td {padding: 0 10px;}",
		".sl-icon {background: url('"+css.u.cIcons+"') no-repeat; display: inline-block; margin: -2px 8px 0px 0px; vertical-align: middle; height: 16px; width: 16px;}",
		".sl-wl {background-position: 0px 0px;}",
		".sl-nm {background-position: 0px -16px;}",
		".sl-ct {background-position: 0px -32px;}",
		".sl-cs {background-position: 0px -48px;}",
		".sl-kttc {background-position: 0px -64px;}",
		".sl-wlife {background-position: 0px -80px;}",
		".sl-as {background-position: 0px -96px;}",
		".sl-wr {background-position: 0px -112px;}",
		// rating profile rules
		".rating-profile {width: 70%; margin: 0px auto;}",
		// settings menu rules
		"#common_menu .menu-settings {text-align: left;}",
		"#common_menu .menu-settings .settingItem {margin: 6px 0px;}",
		"#common_menu .menu-settings label {display: block; line-height: normal; cursor: pointer;}",
		"#common_menu .menu-settings .l-box {display: none;}",
		"#common_menu .menu-settings .b-checkbox {height: 16px; width: 16px; float: left; margin-right: 5px;}",
		"#common_menu .menu-settings .b-checkbox span {height: 16px; width: 16px;}",
		"#common_menu .menu-settings .b-combobox-label__checked {color: #DCDCDC;}",
		"#common_menu .menu-settings .settingItem:hover .b-checkbox {background-position: 0px -34px; box-shadow: 0px 0px 10px 1px rgba(191, 166, 35, 0.15), 0px 0px 3px 1px rgba(191, 166, 35, 0.25);}",
		"#common_menu .menu-settings .settingItem:hover .b-checkbox.b-checkbox__checked {background-position: 0px -68px;}",
		"#common_menu .menu-settings .settingItem:hover .b-combobox-label {color: #DCDCDC;}",
		"#common_menu .menu-settings textarea.l-textarea {background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 2px; color: #FFFFFF; line-height: normal; padding: 5px; min-height: 50px; margin: 5px 0 5px 0;}",
		"#common_menu .menu-settings textarea::-webkit-input-placeholder {color: #FFFFFF;}",
		"#common_menu .menu-settings textarea::-moz-placeholder {color: #FFFFFF;}",
		"#common_menu .menu-settings .b-settingLink {line-height: normal;}",
		"#common_menu .menu-settings .b-settingLink a {cursor: pointer; color: #B1B2B3; text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.5);}",
		"#common_menu .menu-settings .b-settingLink a:hover {color: #FFFFFF; text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.75);}",
		// memberpage rules
		".page-header {padding: 30px 0 30px 0}",
		// button fetch rules
		".b-button-stats {border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 2px; position: absolute; right: 0; top: 9px;}",
		".b-button-stats a {background: rgba(255, 255, 255, 0.1); color: #FFFFFF; cursor: pointer; font-size: 17px; line-height: 45px; display: block; padding: 0px 15px; transition: all 0.2s ease 0s;}",
		".b-button-stats a:hover {background: rgba(229, 177, 46, 0.25);}",
		// rating players rules
		".rating-players {height: 200px;}",
		".rating-players tbody {width: 70%; display: table; margin: 0px auto;}",
		".rating-players_item__data {padding-top: 15px}",
		".rating-players_item__average {padding-top: 10px}",
		".rating-players_stats {font-size: 40px;}",
		// membertable rules
		"#js-playerslist-table {margin-top: -40px;}",
		".rating-table_wn a {cursor: pointer;}",
		""
	];
	style.textContent = styleClan.join("");
	// end style

	// script link
	var clanHead_div = elem("div", "cm-parent-link", sc.link),
	navMenu = d.getElementById('common_menu'),
	navUser = navMenu.getElementsByClassName('cm-menu__user')[0];
	// add script info if user menu exists, else wait
	if (navUser) {
		navUser.insertBefore(clanHead_div, navUser.firstChild);
	}
	else {
		var navLook = new MutationObserver(function() {
			navUser = navMenu.getElementsByClassName('cm-menu__user')[0];
			navUser.insertBefore(clanHead_div, navUser.firstChild);
			navLook.disconnect();
		});
		navLook.observe(navMenu, {childList: true});
	}

	// clan statistic links
	var menu_class = d.getElementsByClassName('menu-top')[0],
	clanMenu_div = elem("div", "menu-clan_links menu-top_item", "<span class='menu-top_link'>"+loc.c01+"<span class='cm-arrow'></span></span>"),
	clanMenu_list = elem("ul", "clan-links cm-sublist", ""),
	clanMenu_list_items = [
		[srv.wl, "<a target='_blank' href='http://wotlabs.net/"+srv.wl+"/clan/"+wg.clan.name+"'><span class='sl-icon sl-wl'></span>WoTLabs</a>"],
		[srv.nm, "<a target='_blank' href='http://noobmeter.com/clan/"+srv.nm+"/"+wg.clan.name+"/"+wg.clan.id+"'><span class='sl-icon sl-nm'></span>Noobmeter</a>"],
		[srv.ct, "<a target='_blank' href='https://clantools.us/servers/"+srv.ct+"/clans?id="+wg.clan.id+"'><span class='sl-icon sl-ct'></span>Clan Tools</a>"],
		[srv.cs, "<a target='_blank' href='http://wotcs.com/clan.php?wid="+wg.clan.id+"'><span class='sl-icon sl-cs'></span>WoT-CS</a>"],
		[srv.kttc, "<a target='_blank' href='http://"+((wg.srv=="ru") ? "" : srv.kttc+".")+"kttc.ru/clan/"+wg.clan.id+"/'><span class='sl-icon sl-kttc'></span>KTTC</a>"],
		[srv.wlife, "<a target='_blank' href='http://en.wot-life.com/"+srv.wlife+"/clan/"+wg.clan.name+"-"+wg.clan.id+"/'><span class='sl-icon sl-wlife'></span>WoT-Life</a>"],
		[srv.as, "<a target='_blank' href='http://stats.teamaway.net/clan/"+wg.clan.id+"/'><span class='sl-icon sl-as'></span>AWAY Stats</a>"],
		[srv.wr, "<a target='_blank' href='http://wotreplays."+srv.wr+"/clan/"+wg.clan.name+"'><span class='sl-icon sl-wr'></span>WoTReplays</a>"]
	];
	linksHnd(clanMenu_list, clanMenu_list_items);
	clanMenu_div.firstElementChild.addEventListener('click', function() {this.classList.toggle('cm-parent-link__opened'); this.nextSibling.classList.toggle('cm-sublist__opened');}, false);
	clanMenu_div.appendChild(clanMenu_list);
	menu_class.appendChild(clanMenu_div);

	// add clan total stats if they exist
	if (wg.p && s.clan) {
		var clanStatValue = d.getElementsByClassName('rating-profile_item');
		if (s.clan.win) {
			clanStatValue[1].innerHTML = "<i class='rating-profile_icon i i__rating-common i__wot-victories'></i><span class='rating-profile_value rating-players_stats js-format-number'>"+colStat(s.clan.win, "wr", 2, "%")+"</span><span class='rating-profile_key'>"+loc.c08+"</span>";
		}
		if (s.clan.wn8) {
			clanStatValue[3].innerHTML = "<i class='rating-profile_icon i i__rating-common i__wot-experience'></i><span class='rating-profile_value rating-players_stats js-format-number'>"+colStat(s.clan.wn8,"wn8",0)+"</span><span class='rating-profile_key'>"+loc.c09+"</span>";
		}
	}

	// check if on memberlist page
	if (wg.m) {
		// formula calculations and variables
		var memObj = {
			cls: d.getElementsByClassName('rating-table_body')[0],
			ids: [],
			num: []
		};
		// memberlist settings
		var clanSet_div = elem("div", "menu-settings menu-top_item", "<span class='cm-parent-link js-cm-dropdown-link'>"+loc.c03+"<span class='cm-arrow'></span></span>"),
		clanSet_list = elem("ul", "cm-sublist", ""),
		enableOnPageload = JSON.parse(localStorage.getItem("statScript_onPageload")),
		enableWhitelist = JSON.parse(localStorage.getItem("statScript_whitelist")),
		enableWhiteListList = localStorage.getItem("statScript_whitelist_list"),
		whiteListArray = (enableWhiteListList) ? enableWhiteListList.split(",") : "",
		clanSet_list_items = [
			settingsHnd("onPageload", loc.c04, enableOnPageload, false),
			settingsHnd("whitelist", loc.c05, enableWhitelist, false, enableWhiteListList),
			settingsHnd("wnRefresh", loc.c06+" [v"+wnExpVers[1]+"]"),
			settingsHnd("cleanStorage", loc.c07),

		];
		linksHnd(clanSet_list, clanSet_list_items);
		clanSet_div.firstElementChild.addEventListener('click', function() {this.classList.toggle('cm-parent-link__opened'); this.nextSibling.classList.toggle('cm-sublist__opened');}, false);
		clanSet_div.appendChild(clanSet_list);
		// add script settings if user menu exists, else wait
		if (navUser) {
			navUser.insertBefore(clanSet_div, navUser.firstChild);
		}
		else {
			var setLook = new MutationObserver(function() {
				navUser = navMenu.getElementsByClassName('cm-menu__user')[0];
				navUser.insertBefore(clanSet_div, navUser.firstChild);
				setLook.disconnect();
			});
			setLook.observe(navMenu, {childList: true});
		}

		// prepare stat fetcher, store stats in localStorage and reload page
		var ratLook = new MutationObserver(function() {
			tableFetch();
			ratLook.disconnect();
		});

		// add manual stat fetching button
		var timeFrame_class = d.getElementsByClassName('timeframe')[0],
		refreshBtn_div = elem("div", "b-button-stats", "<a id='js-wn8-fetch'>"+loc.c10+"</a>");
		refreshBtn_div.addEventListener('click', function() {tableFetch();}, false);
		timeFrame_class.appendChild(refreshBtn_div);

		// fetch stats automatically if enabled or check whitelist for whitelisted clan
		if (statFetch && (enableOnPageload || (enableWhitelist && whiteListArray.indexOf(wg.clan.id) > -1))) {
			ratLook.observe(memObj.cls, {childList: true});
		}
		else {
			// wait for table to be filled before adding wn8
			var clanInsertStatus = false, ratHeadStatus = false,
			ratHead = d.getElementsByClassName('rating-table_head')[0].rows[0],
			ratInsert = new MutationObserver(function(muto) {
				if (muto[0].previousSibling === null) {
					// add clan total stats if they exist
					if (s.clan && clanInsertStatus === false) {
						var clanStatValue = d.getElementsByClassName('rating-players_item');
						if (s.clan.win) {
							clanStatValue[1].innerHTML = "<i class='rating-players_icon i i__rating-common i__wot-victories'></i><span class='rating-players_value rating-players_stats'>"+colStat(s.clan.win, "wr", 2, "%")+"</span><span class='rating-players_key'>"+loc.c08+"</span>";
						}
						if (s.clan.wn8) {
							clanStatValue[3].innerHTML = "<i class='rating-players_icon i i__rating-common i__wot-experience'></i><span class='rating-players_value rating-players_stats'>"+colStat(s.clan.wn8,"wn8",0)+"</span><span class='rating-players_key'>"+loc.c09+"</span>";
						}
						clanInsertStatus = true;
					}
					// table header for wn8
					if (Object.keys(s).length !== 0) {
						if (ratHeadStatus === false) {
							var wnHead = ratHead.insertCell((ratHead.childElementCount == 14) ? 4 : 3);
							wnHead.className = "rating-table_th rating-table_th__key rating-table_wn";
							wnHead.innerHTML = "<a class='table-sorter js-table-sorter js-sort-wn'><i class='table-sorter_icon table-sorter_icon__media i i__table-params i__wot-aeb'></i><span class='table-sorter_key'>WN8</span></a>";
							ratHeadStatus = true;
						}
						// add wn8 for each member
						for (var _rt=0, _rt_len = memObj.cls.rows.length; _rt<_rt_len; _rt++) {
							var row = memObj.cls.rows[_rt],
							id = row.getAttribute('data-account_id'),
							wnRow = row.insertCell((ratHead.childElementCount == 14) ? 3 : 4);
							wnRow.className = "rating-table_td rating-table_td__value js-account-500171710-stats js-format-number";
							wnRow.innerHTML += s[id].wn8;
						}
					}
				}
			});
			ratInsert.observe(memObj.cls, {childList: true});
		}
	}

	function tableFetch() {
		// change status to 'fetching'
		d.getElementById('js-wn8-fetch').textContent = loc.c11;
		// find required info from table player rows
		for (var _rt=0, _rt_len = memObj.cls.rows.length; _rt<_rt_len; _rt++) {
			var id = memObj.cls.rows[_rt].getAttribute('data-account_id'),
			name = memObj.cls.rows[_rt].getElementsByClassName('player_name')[0].innerHTML.match(/[\w\_]+/)[0];
			if (!isNaN(id)) {
				var users = memObj.ids.length,
				index = memObj.ids.indexOf(id);
				s[id] = {u:{name:name,id:id}, v:{frag:0,dmg:0,spot:0,def:0,win:0}, wn8:""};
				if (index>-1) {
					memObj.num[index][memObj.num[index].length] = _rt;
				}
				else {
					memObj.ids[users] = id;
					memObj.num[users] = [_rt];
				}
			}
		}
		s.clan = {wn8:0, win:0, mem: memObj.ids.length};
		// request and retrieve statistics from API
		if (memObj.ids.length > 0) {
			sc.api.i = "http://api.worldoftanks."+((wg.srv == "na") ? "com" : wg.srv)+"/wot/account/info/?application_id="+sc.api[wg.srv]+"&account_id="+memObj.ids.join(',');
			sc.api.v = "http://api.worldoftanks."+((wg.srv == "na") ? "com" : wg.srv)+"/wot/account/tanks/?application_id="+sc.api[wg.srv]+"&account_id="+memObj.ids.join(',');
			reqHnd(sc.api.i, apiInfoHnd);
		}
	}

	// processing information from player API
	function apiInfoHnd(resp) {
		var data = JSON.parse(resp).data;
		for (var a in data) {
			if (data.hasOwnProperty(a)) {
				var pData = data[a];
				if (pData !== null) {
					// store stats
					s[pData.account_id].u = {
						name: pData.nickname,
						id: pData.account_id,
						cid: pData.clan_id,
						bat: pData.statistics.all.battles,
						win: (pData.statistics.all.wins/pData.statistics.all.battles)*100,
						dmg: pData.statistics.all.damage_dealt/pData.statistics.all.battles,
						frag: pData.statistics.all.frags/pData.statistics.all.battles,
						spot: pData.statistics.all.spotted/pData.statistics.all.battles,
						def: pData.statistics.all.dropped_capture_points/pData.statistics.all.battles,
						wgr: pData.global_rating,
						lng: pData.client_language
					};
					s.clan.win += (!isNaN(s[pData.account_id].u.win)) ? s[pData.account_id].u.win : 0;
				}
			}
		}
		reqHnd(sc.api.v, apiVehHnd);
	}

	// processing information from vehicle API and calculate WN8
	function apiVehHnd(resp) {
		var data = JSON.parse(resp).data;
		for (var p in data) {
			if (data.hasOwnProperty(p)) {
				var vData = data[p];
				if (vData !== null) {
					var rWin, rDmg, rFrag, rSpot, rDef, wn8 = 0;
					if (s[p].u.bat > 0) {
						for (var v in vData) {
							if (vData.hasOwnProperty(v)) {
								// go through each vehicle to get expected stats
								for (var _so=0, _so_len = statObj.length; _so<_so_len; _so++) {
									if (statObj[_so].IDNum == vData[v].tank_id) {
										var vehStat = statObj[_so],
										dataBattles = vData[v].statistics.battles;
										s[p].v.frag += vehStat.expFrag    * dataBattles;
										s[p].v.dmg  += vehStat.expDamage  * dataBattles;
										s[p].v.spot += vehStat.expSpot    * dataBattles;
										s[p].v.def  += vehStat.expDef     * dataBattles;
										s[p].v.win  += vehStat.expWinRate * dataBattles;
										break;
									}
								}
							}
						}
						// start calculating wn8
						rWin  = Math.max(((s[p].u.win /(s[p].v.win /s[p].u.bat)-0.71)/(1-0.71)),0);
						rDmg  = Math.max(((s[p].u.dmg /(s[p].v.dmg /s[p].u.bat)-0.22)/(1-0.22)),0);
						rFrag = Math.max(Math.min(rDmg+0.2,((s[p].u.frag/(s[p].v.frag/s[p].u.bat)-0.12)/(1-0.12))),0);
						rSpot = Math.max(Math.min(rDmg+0.1,((s[p].u.spot/(s[p].v.spot/s[p].u.bat)-0.38)/(1-0.38))),0);
						rDef  = Math.max(Math.min(rDmg+0.1,((s[p].u.def /(s[p].v.def /s[p].u.bat)-0.10)/(1-0.10))),0);
						wn8 = 980*rDmg + 210*rDmg*rFrag + 155*rFrag*rSpot + 75*rDef*rFrag + 145*Math.min(1.8,rWin);
					}
					// store wn8 and add to clan total
					s[p].wn8 = colStat(wn8,"wn8",0);
					s.clan.wn8 += wn8;
					// change status to 'fetched'
					d.getElementById('js-wn8-fetch').textContent = loc.c12;
				}
			}
		}
		// calculate average wn8 / winrate and store everything in localStorage, then reload page
		s.clan.wn8 = s.clan.wn8/s.clan.mem;
		s.clan.win = s.clan.win/s.clan.mem;
		localStorage.setItem("statScriptValues_"+wg.clan.id, JSON.stringify(s));
		localStorage.setItem("statScriptDate_"+wg.clan.id, Date.now());
		location.reload();
	}

	// helper functions
	// filter
	function filter(input, type) {
		var inputStr = input.toString();
		switch(type) {
			case (1): // input string into number
				return parseFloat(inputStr.replace(/[^\d]/g,""));
			case (2): // output number with locale symbol
				return inputStr.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1"+loc.sym);
			case (3): // remove all symbols
				return inputStr.replace(/[^\w]/g,"");
			default:
				console.error("Error filtering: ", input);
				return input;
		}
	}

	// colouring
	function colStat(input, type, dec, sym) {
	var color = colArr.dft[0],
		output = input.toFixed(dec);
		if (sym) {
			output += sym;
		}
		if (input >= 1000) {
			output = input.toFixed(dec).toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1"+loc.sym);
		}
		for (var c in colArr) {
			if (colArr.hasOwnProperty(c)) {
				if (input >= colArr[c][colArr.id[type]]) {
					color = colArr[c][0]; break;
				}
			}
		}
		return "<font color='"+color+"'>"+output+"</font>";
	}

	// quick creation of element
	function elem(tag, name, html, type) {
		var element = d.createElement(tag);
		if (name) {
			element.className = name;
		}
		if (html) {
			if (/</.test(html)) {
				element.innerHTML = html;
			}
			else {
				element.textContent = html;
			}
		}
		if (type) {
			element.type = type;
		}
		return element;
	}

	// settings handler
	function settingsHnd(name, text, state, dftState, wlist) {
		var listItem = elem("li", "settingItem", ""),
		listItems = d.createDocumentFragment();
		if (name == "wnRefresh") {
			var refreshBtn = elem("div", "b-settingLink", "<a>"+text+"</a>");
			refreshBtn.addEventListener('click', function() {localStorage.removeItem("wnExpValues"); location.reload();}, false);
			listItems.appendChild(refreshBtn);
		}
		else if (name == "cleanStorage") {
			var cleanBtn = elem("div", "b-settingLink", "<a>"+text+"</a>");
			cleanBtn.addEventListener('click', function() {localStorage.clear(); location.reload();}, false);
			listItems.appendChild(cleanBtn);
		}
		else {
			var optCheckDiv = elem("div", "b-checkbox", "<span class='b-checkbox_checker'></span>"),
			optLabel = elem("label", "b-combobox-label", text),
			optCheck = elem("input", "l-box", "", "checkbox");
			optLabel.htmlFor = name;
			optCheck.name = name;
			optCheck.id = name;
			if (state) {
				optCheckDiv.classList.add("b-checkbox__checked");
				optLabel.classList.add("b-combobox-label__checked");
			}
			optCheck.checked = (state !== undefined) ? state : dftState;
			optCheck.addEventListener('click', function() {
				localStorage.setItem('statScript_' + this.name, this.checked);
				d[this.name] = this.checked;
				this.parentNode.classList.toggle('b-checkbox__checked');
				this.parentNode.nextSibling.classList.toggle('b-combobox-label__checked');
				return this.checked;
			}, false);
			d[optCheck.name] = optCheck.checked;
			optCheckDiv.insertBefore(optCheck, optCheckDiv.firstChild);
			listItems.appendChild(optCheckDiv);
			listItems.appendChild(optLabel);
			if (name == "whitelist") {
				var optText = elem("textarea", "l-textarea", "");
				optText.placeholder = "Add clanID seperated by comma without spaces: 500004502,500010805";
				if (wlist) {
					optText.value = wlist;
				}
				optText.addEventListener('input', function() {
					localStorage.setItem('statScript_whitelist_list', optText.value.split(","));
				}, false);
				listItems.appendChild(optText);
			}
		}
		listItem.appendChild(listItems);
		return listItem;
	}

	// links handler
	function linksHnd(parent, links) {
		var uRows = d.createDocumentFragment();
		for (var _l=0, _l_len = links.length; _l<_l_len; ++_l) {
			if (links[_l] instanceof HTMLElement) {
				uRows.appendChild(links[_l]);
			}
			else {
				uRows.appendChild((links[_l][0] && links[_l][1]) ? elem("li", "", links[_l][1]) : elem("li", "statname", links[_l][0]));
			}
		}
		parent.appendChild(uRows);
	}
	// end helper functions

	// wnefficiency handler
	function wnHnd(resp) {
		localStorage.setItem("wnExpValues", resp);
		localStorage.setItem("wnExpDate", Date.now());
		localStorage.setItem("wnExpVers", JSON.stringify([sc.vers, JSON.parse(resp).header.version]));
		location.reload();
	}
	function wnHnd_error(error) {
		console.error("Error accessing WNEfficiency.net", error);
	}
	// end wnefficiency handler

	// retrieval function
	function reqHnd(url, handler, error) {
		GM_xmlhttpRequest({
			method: "GET",
			url: url,
			headers: {
				"Accept": "text/xml"
			},
			onload: function(resp) {
				if (resp.readyState == 4 && resp.status == 200 && resp.statusText == "OK") {
					handler(resp.responseText);
				}
				else {
					error(resp.responseText);
				}
			},
			onerror: function(resp) {
				error(resp.responseText);
			}
		});
	}
}(window));