WoTStatScript - ForumsExtendedStat

Adds stats and links for posts on official World of Tanks forums

Fra og med 16.02.2016. Se den nyeste version.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name        WoTStatScript - ForumsExtendedStat
// @version     0.9.13.0.5
// @description Adds stats and links for posts on official World of Tanks forums
// @author      Orrie
// @contributor seriych
// @namespace   http://forum.worldoftanks.eu/index.php?/topic/263423-
// @icon        http://dl.dropboxusercontent.com/u/12497046/wot/projects/statscript/img/icon.png
// @include     /^http:\/\/forum\.worldoftanks\.(eu|com|ru|asia|kr)\/\S+(\/topic\/|\?showtopic=)/
// @include     /^http:\/\/forum\.worldoftanks\.(eu|com|ru|asia|kr)\/index\.php\?app=members&module=messaging&section=view&do=showConversation&topicID=\d+/
// @include     /^http:\/\/forum\.worldoftanks\.(eu|com|ru|asia|kr)\/index\.php\?\/forum/\S+/
// @grant       GM_xmlhttpRequest
// @connect     www.wnefficiency.net
// @connect     api.worldoftanks.eu
// @connect     api.worldoftanks.ru
// @connect     api.worldoftanks.com
// @connect     api.worldoftanks.asia
// @connect     api.worldoftanks.kr
// @license     MIT License
// ==/UserScript==
(function() {
	// global vars
	var d = document;

	// get server info and webpage
	var wg = {host:d.location.host, href:d.location.href, clan:{}};
		wg.srv = wg.host.match(/\.(eu|ru|com|asia|kr)/)[1].replace(/com/,"na");
		wg.topic = /(\/topic\/|\?showtopic=|messaging\&)/.test(wg.href);
		wg.forum = /\/forum\//.test(wg.href);
		wg.login = !!d.getElementsByClassName('js-cm-login-link')[0];

	// server, API and cluster settings
	var sc = {
		vers: "0.9.13.0.5",
		host: "http://greasyfork.org/scripts/660-wotstatscript-forumsextendedstat",
		top: {
			eu: "http://forum.worldoftanks.eu/index.php?showtopic=263423",
			na: "http://forum.worldoftanks.com/index.php?showtopic=404652"
		},
		api: {
			ru: "98ca7c4fb108175b67d6505b9c3f3ebd",
			eu: "a7595640a90bf2d19065f3f2683b171c",
			com: "bf5dba0efd444d75147b6222dd903fd2",
			asia: "95f8713eccd322e52dbf521dbd28b19c",
			kr: "ffea0f1c3c5f770db09357d94fe6abfb"
		},
		sym: ",",
		wn: "http://www.wnefficiency.net/exp/expected_tank_values_latest.json",
		date: Date.now(),
		dateFormat: {ru: "ru-RU", eu: "en-GB", na: "en-US", asia: "en-AU", kr: "ko-KR"}
	};
	// script threadlink
		sc.link = "<div class='b-scriptlink'><a target='_blank' href="+sc.host+">Script</a> v"+sc.vers+" - <a target='_blank' href="+((wg.srv == "na") ? sc.top.na : sc.top.eu)+">Thread</a></div>";

	// 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)
	};

	// external site support - wotlabs, noobmeter, wot-news, wotstats, wotcs, wot-life, wotstats.com.au and wotreplays
	var srv = {
		s: "en", wl: false, nm: false, vb: false, ws: false, wr: false, ct: false, wlf: false
	};
	switch(wg.srv) {
		case ("eu"): // eu server
			srv.wl = srv.nm = srv.vb = srv.ws = srv.wr = srv.ct = srv.wlf = wg.srv;
			break;
		case ("ru"): // ru server
			srv.wl = srv.nm = srv.vb = srv.ws = srv.wr = srv.ct = srv.wlf = wg.srv;
			srv.s = "ru";
			sc.sym = " ";
			break;
		case ("com"): // na server
			srv.wl = srv.nm = srv.vb = srv.ws = srv.ct = "na"; srv.wr = "com";
			break;
		case ("asia"): // asia server
			srv.wl = srv.nm = srv.vb = srv.ws = "sea"; srv.ct = wg.srv; srv.wr = "com";
			break;
		case ("kr"): // korean server
			srv.wl = srv.nm = srv.vb = srv.ws = srv.ct = srv.ch = wg.srv; srv.wr = "com";
			break;
		default: break;
	}

	// data uri
	var uri = {
		icon_arrow:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPwAAAAJCAMAAAAhKrH/AAAAV1BMVEUAAAD///+TKCf9AQmTLiX9AQmTMir9AQmTLif9AQmTMSz9AQmTMir9AQmTMyn9AQmTMirvGgKTMirsIAGTMirwGQOTMiqTMirsIAGaNDGgNzfqJwDrJABtE0DNAAAAGnRSTlMAABERIiIzM0REVVVmZnd3iIqZmrvDzN3g7thzQuwAAACHSURBVHja5dVLDsIwDEXRCySlP0IMoXXs7H+dDBASA1bQ3B0cPclm2Fe2wrfTQeO3qwqqAKWek80HxfO/l1/EBRgtU2tf+KkJ7TO9hdVSV3jU42f6ZClY6Qt/d4n+BGol29jTwQN1pE2QbA610BVefImuwL7xsNAXXhVpEYY8kNfO/rwsyA3ekEsOT2YDLE8AAAAASUVORK5CYII=",
		q_mark: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAANCAYAAACgu+4kAAAAh0lEQVQoz2OwsbGxtre3jwTiBBJxJEgvA4jBQCYA6wWZhkVOFIjLgPgOEH8A4llArIDFgARcBsgCsRkQywGxLhC3AXEtKQYgA5DN6UCcRo4BEkCcDcSVQMxLqgHcQJwPxNVAzIMjEPEaIAXEJUCcgScWiAoDBnINEAbieiCuobkBlKVESvMCADnAReqxtj3zAAAAAElFTkSuQmCC"
	};

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

	// style contents
	var style = elem("style", "wotstatscript", "", "text/css"),
		styleText = [
			// script header rules
			"#common_menu .cm-menu__user > *:not(.cm-notifications):not(.js-cm-user-menu-dropdown):not(.js-cm-dropdown-for-mobile-only) {display: inline-block}",
			"#common_menu .cm-parent-link:hover {cursor: inherit; color: #707273 !important;}",
			"#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 .cm-get-gold-link {margin: 0 12px;}",
			"#common_menu .cm-menu__user .cm-parent-link {font-size: 13px; padding: 0 8px 0 10px;}",
			// settings menu rules
			"#common_menu .menu-settings {text-align: left;}",
			"#common_menu .menu-settings .cm-user-menu-link {margin: 0;}",
			"#common_menu .menu-settings .cm-user-menu {padding: 15px; right: unset;}",
			"#common_menu .menu-settings .cm-parent-link:hover {cursor: pointer;}",
			"#common_menu .menu-settings label {display: table; 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 .b-combobox-label:hover {color: #DCDCDC;}",
			"#common_menu .menu-settings .settingItem .b-combobox-label: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 .b-combobox-label:hover .b-checkbox.b-checkbox__checked {background-position: 0px -68px;}",
			"#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; min-width: 175px;}",
			"#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: 26px;}",
			"#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);}",
			// forum rules
			".topic_list {table-layout: auto}",
			".col_f_stats {width: 200px;}",
			".col_f_preview {width: 10px !important;}",
			".col_f_views {width: auto;}",
			".col_f_post {width: auto;}",
			".col_f_stats .i-xvm-lang {margin: 6px 0 0 0;}",
			".t-row-stats {float: right; table-layout: fixed; width: 175px;}",
			".realm_ru .t-row-stats {width: 200px;}",
			"table.ipb_table .t-row-stats td {border-bottom: 0; font-size: 11px; padding: 0;}",
			"#announcements .t-row-stats td {border-bottom: 0;}",
			".s-no-stats {color: #A03737; display: table; font-size: 14px; margin: 0 auto;}",
			// thread rules
			".author_info {min-height: 310px; padding: 0 10px 10px 14px;}",
			".user_details > br {display: none;}",
			".author_info .member_title.member_banned {color: #CD3333;}",
			".basic_info {margin: 0 0 4px;}",
			".post_count.margin-bottom {margin: 0 0 5px;}",
			".battles_count {display: none;}",
			".i-xvm-lang {vertical-align: text-top;}",
			".t-table-stats {margin: 5px 0; width: auto;}",
			".t-table-stats td {padding: 0 5px 0 0; line-height: 16px;}",
			".t-table-stats td:last-of-type {font-weight: bold;}",
			".b-table-links {height: 25px; margin: 5px 0px 0px;}",
			".t-table-links {background: #EDEDED; border: 1px solid #d5d5d5; border-radius: 3px; box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1), 0 0 3px 3px rgba(255, 255, 255, 0.2); display: inline-block; overflow: hidden; padding: 3px 3px 0; position: absolute; text-overflow: ellipsis; white-space: nowrap; height: "+((web.chrome) ? "20px" : "25px")+"; width: 90px; z-index: 1;}",
			".t-table-links:hover {border-color: #7D7D7D; height: auto; width: auto;}",
			".t-table-links tbody {display: table; width: 180px;}",
			".t-table-links td {padding: 0 0 2px; font-weight: bold;}",
			".t-table-links td a { background: url("+uri.icon_arrow+") no-repeat scroll 0 2px rgba(0, 0, 0, 0); padding: 0 0 0 10px; vertical-align: middle;}",
			".t-table-links td a:hover {background: url("+uri.icon_arrow+") no-repeat scroll -244px 2px rgba(0, 0, 0, 0);}",
			".t-table-links tr:last-of-type td {}",
			// korean realm widths
			".realm_kr .t-table-links {width: 108px;}",
			".realm_kr .t-table-links:hover {width: 215px;}",
			".realm_kr .t-table-links tbody {width: 215px;}"
		];
		style.textContent = styleText.join("");
		d.head.appendChild(style);
	// end style

	// colour scale array
	var colArr = {
		//      col        wr  bat    wn8   wn7   eff   nm    pr
		sUni: [ "#5A3175", 65, 30000, 2900, 2050, 2050, 2000       ], // 99.99% super unicum
		uni:  [ "#83579D", 60, 25000, 2450, 1850, 1800, 1950, 9930 ], // 99.90% unicum
		gr8:  [ "#3972C6", 56, 21000, 2000, 1550, 1500, 1750, 8525 ], // 99.00% great
		vGud: [ "#4099BF", 54, 17000, 1600, 1350                   ], // 95.00% very good
		good: [ "#4D7326", 52, 13000, 1200, 1100, 1200, 1450, 6340 ], // 82.00% good
		aAvg: [ "#849B24", 50, 10000,  900                         ], // 63.00% above average
		avg:  [ "#CCB800", 48,  7000,  650,  900,  900, 1250, 4185 ], // 40.00% average
		bAvg: [ "#CC7A00", 47,  3000,  450,  700,  600, 1150, 2020 ], // 20.00% below average
		bas:  [ "#CD3333", 46,  1000,  300,  500                   ], //  6.00% basic
		beg:  [ "#930D0D",  0,     0,    0,    0,    0,    0, 0    ], //  0.00% beginner
		dft:  [ "#6B6B6B" ], // default
		id: { "col": 0, "wr": 1, "bat": 2, "wn8": 3, "wn7": 4, "eff": 5, "nm": 6, "pr": 7 }  // type identifier
	};

	// localization
	var loc = [
		{ en: "Client", ru: "Клиент"},
		{ en: "Winrate:", ru: "Винрейт:"},
		{ en: "Battles:", ru: "Боев:"},
		{ en: "Rating:", ru: "Рейтинг:"},
		{ en: "WN8:", ru: "WN8:"},
		{ en: "Please Login for Stats", ru: "Please Login for Stats"},
		{ en: "No Stats Found", ru: "No Stats Found"},
		{ en: "Script Menu", ru: "Script Menu"},
		{ en: "Refresh WN8 Table", ru: "Refresh WN8 Table"}
		//{ en: "f00_en", ru: "f00_ru"},
	];
	// process localization
	for (var _l=0, l_len = loc.length; _l<l_len; _l++) {
		loc[_l] = loc[_l][srv.s];
	}

	// script link
	var userLink_div = elem("div", "cm-parent-link", sc.link),
	userSet_div = elem("div", "menu-settings menu-top_item", "<a class='cm-user-menu-link' href='#'><span class='cm-user-menu-link_cutted-text'>"+loc[7]+"</span><span class='cm-arrow'></span></span>"),
	userSet_list = elem("ul", "cm-user-menu", "<li class='settingItem'><div class='b-settingLink'><a>"+loc[8]+" [v"+wnExpVers[1]+"]</a></div></li>"),
	navMenu = d.getElementById('common_menu'),
	navUser = navMenu.getElementsByClassName('cm-menu__user')[0];
	userSet_div.firstElementChild.addEventListener('click', function() {this.classList.toggle('cm-user-menu-link__opened'); this.nextSibling.classList.toggle('cm-user-menu__opened');}, false);
	userSet_list.firstElementChild.firstElementChild.addEventListener('click', function() {localStorage.removeItem("wnExpValues"); location.reload();}, false);
	userSet_div.appendChild(userSet_list);
	if (navUser) {
		navUser.insertBefore(userLink_div, navUser.firstChild);
		navUser.insertBefore(userSet_div, navUser.firstChild);
	}
	else {
		var navLook = new MutationObserver(function() {
			var navUser = navMenu.getElementsByClassName('cm-menu__user')[0];
			navUser.insertBefore(userLink_div, navUser.firstChild);
			navUser.insertBefore(userSet_div, navUser.firstChild);
			navLook.disconnect();
		});
		navLook.observe(navMenu, {childList: true});
	}

	// formula calculations and variables
	// create global post variable
	var postObj = {
		post: d.querySelectorAll(".post_wrap, .post_wrap__wg"),
		span: d.querySelectorAll("span.desc.lighter.blend_links"),
		cls: [],
		ids: [],
		num: []
	},
	s = {};
	switch(true) {
		case (wg.topic):
			postObj.cls = postObj.post; break;
		case (wg.forum):
			postObj.cls = postObj.span; break;
		default: break;
	}

	// fetch userids and store all posts into one obj for later use
	if (wg.topic || (wg.forum && wg.login === false)) {
		for (var _t=0, _t_len = postObj.cls.length; _t<_t_len; _t++) {
			var id;
			switch(true) {
				case (wg.topic):
					id = postObj.post[_t].getElementsByClassName("ipsUserPhotoLink")[0].getAttribute('href').match(/\-(\d+)\//)[1]; break;
				case (wg.forum):
					var id_url = postObj.span[_t].getElementsByClassName("url")[0];
					if (id_url) {
						id = id_url.getAttribute('href').match(/\-(\d+)\//)[1];
					}
					break;
				default: break;
			}
			if (!isNaN(id)) {
				var users = postObj.ids.length,
				index = postObj.ids.indexOf(id);
				s[id] = {u:{},v:{frag:0,dmg:0,spot:0,def:0,win:0},wn8:""};
				if (index>-1) {
					postObj.num[index][postObj.num[index].length] = _t;
				}
				else {
					postObj.ids[users] = id;
					postObj.num[users] = [_t];
				}
			}
		}
	}
	else {
		navUser.insertBefore(elem("div", "cm-parent-link b-login-msg", "<div>"+loc[5]+"</div>"), navUser.firstChild);
	}

	// request and retrieve statistics from API
	if (postObj.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="+postObj.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="+postObj.ids.join(',');
		reqHnd(sc.api.i, apiInfoHnd);
	}
	else {
		console.error("No post IDs found or not logged in");
	}

	// 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
					var pDataStats = pData.statistics.all;
					s[pData.account_id].u = {
						name: pData.nickname,
						id: pData.account_id,
						cid: pData.clan_id,
						bat: pDataStats.battles,
						win: (pDataStats.wins/pDataStats.battles)*100,
						dmg: pDataStats.damage_dealt/pDataStats.battles,
						frag: pDataStats.frags/pDataStats.battles,
						spot: pDataStats.spotted/pDataStats.battles,
						def: pDataStats.dropped_capture_points/pDataStats.battles,
						wgr: pData.global_rating,
						lng: pData.client_language,
						ban: pData.ban_time
					};
				}
				else {
					// store stats
					s[parseFloat(a)].u = {
						bat: 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)) {
								for (var _so=0, _so_len = statArr.length; _so<_so_len; _so++) {
									if (statArr[_so].IDNum == vData[v].tank_id) {
										var vehStat = statArr[_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;
									}
								}
							}
						}
						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
					s[p].wn8 = colStat(wn8,"wn8",0);
				}
			}
		}
		statInsert();
	}

	// insert stats and links to every post
	function statInsert() {
		for (var y in s) {
			if (s.hasOwnProperty(y)) {
				var iPost = postObj.ids.indexOf(y), flag;
				if (iPost >- 1 && s[y].u.id) {
					if (wg.topic) {
						var userStats = [
							"<td>"+loc[1]+"</td><td>"+colStat((s[y].u.bat > 0) ? s[y].u.win : 0,"wr",2,"%")+"</td>",
							"<td>"+loc[2]+"</td><td>"+colStat(s[y].u.bat,"bat",0,"")+"</td>",
							"<td>"+loc[3]+"</td><td>"+colStat(s[y].u.wgr,"pr",0,"")+"</td>",
							"<td>"+loc[4]+"</td><td>"+s[y].wn8+"</td>"
						],
						userLinks = [
							[
								["<a target='_blank' href='http://worldoftanks."+((wg.srv == "na") ? "com" : wg.srv)+"/community/accounts/"+s[y].u.id+"-"+s[y].u.name+"/'>Player Profile</a>"],
								[srv.wl, "<a target='_blank' href='http://wotlabs.net/"+srv.wl+"/player/"+s[y].u.name+"'>WoTLabs</a>"]
							],
							[
								[srv.vb, "<a target='_blank' href='http://www.vbaddict.net/player/"+s[y].u.name.toLowerCase()+"-"+srv.vb+"'>vBAddict</a>"],
								[srv.nm, "<a target='_blank' href='http://noobmeter.com/player/"+srv.nm+"/"+s[y].u.name+"'>Noobmeter</a>"]
							],
							[
								[srv.ws, "<a target='_blank' href='http://wotstats.org/stats/"+srv.ws+"/"+s[y].u.name+"/'>WoTstats</a>"],
								[srv.ct, "<a target='_blank' href='http://clantools.us/servers/"+srv.ct+"/players?id="+s[y].u.id+"'>Clan Tools</a>"]
							],
							[
								[srv.wr, "<a target='_blank' href='http://wotreplays."+srv.wr+"/player/"+s[y].u.name+"'>WoTReplays</a>"],
								(wg.srv=="ru") ? [srv.wr, "<a target='_blank' href='http://wots.com.ua/user/stats/"+s[y].u.name+"'>WoTS.com.ua</a>"] : [srv.wlf, "<a target='_blank' href='http://en.wot-life.com/"+srv.wlf+"/player/"+s[y].u.name+"/'>WoT-Life</a>"]
							]
						];
						for (var _i=0, _i_len = postObj.num[iPost].length; _i<_i_len; _i++) {
							var groupTitle = postObj.post[postObj.num[iPost][_i]].getElementsByClassName("group_title")[0],
							basicInfo = postObj.post[postObj.num[iPost][_i]].getElementsByClassName("basic_info")[0],
							infoClass = postObj.post[postObj.num[iPost][_i]].getElementsByClassName("author_info")[0],
							statTable = elem("table", "t-table-stats", ""),
							urlDiv = elem("div", "b-table-links", ""),
							urlTable = elem("table", "t-table-links", "<tbody></tbody>");
							flag = elem("img", "i-xvm-lang", "", "", "https://bytebucket.org/seriych/worldoftanksforumextendedstat.user.js/raw/tip/data/img/lang/"+s[y].u.lng+".png");
							for (var _sr=0, _sr_len = userStats.length; _sr<_sr_len; ++_sr) {
								statTable.appendChild(elem("tr", "", userStats[_sr]));
							}
							for (var _l=0, _l_len = userLinks.length; _l<_l_len; ++_l) {
								var uRow = elem("tr", "", "");
								for (var _lr=0, _lr_len = userLinks[_l].length; _lr<_lr_len; ++_lr) {
									uRow.appendChild((userLinks[_l][_lr][0] && userLinks[_l][_lr][1]) ? elem("td", "", userLinks[_l][_lr][1]) : elem("td", "", userLinks[_l][_lr][0]));
								}
								urlTable.firstElementChild.appendChild(uRow);
							}
							if (wg.srv !== "ru") {
								groupTitle.appendChild(flag);
							}
							flag.title = s[y].u.lng.toUpperCase()+" "+loc[0];
							flag.addEventListener('error', function(){this.src=uri.q_mark;});
							if (s[y].u.ban) {
								var memTitle = postObj.post[postObj.num[iPost][_i]].getElementsByClassName("member_title")[0];
								memTitle.textContent = "Banned: "+ new Date(s[y].u.ban*1000).toLocaleString(sc.dateFormat[wg.srv]);
								memTitle.classList.add("member_banned");
							}
							basicInfo.insertBefore(statTable, basicInfo.lastElementChild);
							urlDiv.appendChild(urlTable);
							infoClass.appendChild(urlDiv);
						}
					}
					else if (wg.forum) {
						for (var _r=0, _r_len = postObj.num[iPost].length; _r<_r_len; _r++) {
							var statCell, id_url = postObj.span[postObj.num[iPost][_r]].getElementsByClassName("url")[0],
							threadRow = postObj.span[postObj.num[iPost][_r]].parentNode.parentNode,
							threadRowClsList = threadRow.classList;
							if (threadRowClsList.contains("announcement")) {
								statCell = threadRow.insertCell(1);
							}
							else if (threadRowClsList.contains("__topic")) {
								statCell = threadRow.insertCell(3);
							}
							statCell.className = "col_f_stats";
							if (!id_url || s[y].u.bat === 0) {
								statCell.appendChild(elem("span", "s-no-stats", loc[6]));
							}
							else {
								var statsRow = [
									"<td>"+loc[1]+"</td><td>"+colStat((s[y].u.bat > 0) ? s[y].u.win : 0,"wr",2,"%")+"</td><td>"+loc[2]+"</td><td>"+colStat(s[y].u.bat,"bat",0,"")+"</td>",
									"<td>"+loc[3]+"</td><td>"+colStat(s[y].u.wgr,"pr",0,"")+"</td><td>"+loc[4]+"</td><td>"+s[y].wn8+"</td>",
								],
								rowTable = elem("table", "t-row-stats", "");
								flag = elem("img", "i-xvm-lang", "", "", "https://bytebucket.org/seriych/worldoftanksforumextendedstat.user.js/raw/tip/data/img/lang/"+s[y].u.lng+".png");
								for (var _rr=0, _rr_len = statsRow.length; _rr<_rr_len; ++_rr) {
									rowTable.appendChild(elem("tr", "", statsRow[_rr]));
								}
								if (wg.srv !== "ru") {
									statCell.appendChild(flag);
								}
								flag.title = s[y].u.lng.toUpperCase()+" "+loc[0];
								flag.addEventListener('error', function(){this.src=uri.q_mark;});
								statCell.appendChild(rowTable);
							}
						}
					}
				}
			}
		}
	}

	// helper functions
	// 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"+sc.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, src) {
	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;}
		if (src) {element.src = src;}
		return element;
	}

	// localStorage handler
	function locStorage(name, data, type, mode) {
		var storage;
		switch(type) {
			case ("set"):
				if (mode == "string") {
					data = JSON.stringify(data);
				}
				storage = localStorage.setItem(name, data);
				break;
			case ("get"):
				storage = localStorage.getItem(name);
				if (mode == "parse") {
					storage = JSON.parse(storage);
				}
				break;
			default: break;
		}
		return storage;
	}
	// end helper functions

	// wnefficiency handler
	function wnHnd(resp) {
		locStorage("wnExpValues", resp, "set");
		locStorage("wnExpDate", sc.date, "set");
		locStorage("wnExpVers", [sc.vers, JSON.parse(resp).header.version], "set", "string");
		location.reload();
	}
	// end wnefficiency handler

	// request handler
	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));