WoTStatScript - Tournament Teams

More info for World of Tanks tournament teams

当前为 2015-10-14 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        WoTStatScript - Tournament Teams
// @version     0.9.10.0.1
// @description More info for World of Tanks tournament teams
// @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://worldoftanks.eu/*/teams/*/
// @include     http://worldoftanks.com/*/teams/*/
// @include     http://worldoftanks.ru/*/teams/*/
// @include     http://worldoftanks.asia/*/teams/*/
// @include     http://worldoftanks.kr/*/teams/*/
// @grant       GM_xmlhttpRequest
// @license     MIT License
// ==/UserScript==
(function () {
// global vars
var d = document;

// get server info and webpage
var wg = {
	srv: d.location.host.match(/\.(eu|ru|com|asia|kr)/)[1]
};

// server, API and cluster settings
var sc = {
	vers: "0.9.10.0.1",
	host: "http://greasyfork.org/en/scripts/13064-wotstatscript-tournament-teams",
	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",
		com: "bf5dba0efd444d75147b6222dd903fd2",
		asia: "95f8713eccd322e52dbf521dbd28b19c",
		kr: "ffea0f1c3c5f770db09357d94fe6abfb"
	},
	sym: ",",
	wn: "http://www.wnefficiency.net/exp/expected_tank_values_latest.json"
};

// 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 >= Date.now(), // 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 = [
		".l-sidebar {margin: 0 0 0 20px}",
		".b-profile-header {font-family: Arial;}",
		".b-scriptlink {background: rgba(0, 0, 0, 0.09); box-shadow: 0 0 1px 1px rgba(255, 255, 255, 0.15) inset, 0 0 38px 1px rgba(0, 0, 0, 0.3) inset, 0 0 23px 1px rgba(255, 255, 255, 0.02), 0 0 5px 1px rgba(0, 0, 0, 0.5) inset; color: #606061; border-left: 1px solid #000000; border-right: 1px solid #000000; text-align: center; padding: 7px 0 6px;}",
		".t-table th.stat-total {text-align: center;}",
		".t-table th.stat-total span {margin: 0 15px;}",
		".b-user {width: 50%;}",
		".b-user .xvm-lang {margin: 0 0 -1px 3px;}",
		".b-user .stat {float: right;}",
		".b-user .stat-win {display: inline-block; width: 60px;}",
		".b-user .stat-rat {display: inline-block; text-align: right; width: 32px;}"
	];
	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
};

// scriptlink
var sidebar_class = d.getElementsByClassName('l-sidebar')[0],
scriptlink = elem("div", "b-profile-header", "<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>");
sidebar_class.insertBefore(scriptlink, sidebar_class.firstElementChild);

// create global post variable
var postObj = {
	cls: d.getElementsByClassName("b-user"),
	ids: [],
	num: []
},
s = {};

// fetch userids and store all posts into one obj for later use
for (var _t=0, _t_len = postObj.cls.length; _t<_t_len; _t++) {
	if (postObj.cls[_t].firstElementChild) {
		var id = postObj.cls[_t].firstElementChild.getAttribute('href').match(/\/(\d+)\-/)[1];
		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];
			}
		}
	}
}
s.clan = {wn8:0, win:0, mem: postObj.ids.length};
// request and retrieve statistics from API
if (postObj.ids.length > 0) {
	sc.api.i = "http://api.worldoftanks."+wg.srv+"/wot/account/info/?application_id="+sc.api[wg.srv]+"&account_id="+postObj.ids.join(',');
	sc.api.v = "http://api.worldoftanks."+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
				};
				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)) {
							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 and add to clan total
				s[p].wn8 = colStat(wn8,"wn8",0);
				s.clan.wn8 += wn8;
			}
		}
	}
	// calculate average wn8 / winrate
	s.clan.wn8 = s.clan.wn8/s.clan.mem;
	s.clan.win = s.clan.win/s.clan.mem;
	statInsert();
}

// insert stats and links to every post
function statInsert() {
	var teamTable = d.getElementsByClassName("t-table")[0];
	teamTable.rows[0].cells[0].colSpan = "1";
	teamTable.rows[0].appendChild(elem("th", "stat-total", "<span>WN8: "+colStat(s.clan.wn8,"wn8",0)+"</span><span>WR: "+colStat(s.clan.win,"wr",2,"%")+"</span>"));
	for (var y in s) {
		if (s.hasOwnProperty(y)) {
			var iCell = postObj.ids.indexOf(y);
			if (iCell >- 1) {
				for (var _i=0, _i_len = postObj.num[iCell].length; _i<_i_len; _i++) {
					var cell = postObj.cls[postObj.num[iCell][_i]],
					flag = elem("img", "xvm-lang", "", "", "https://bytebucket.org/seriych/worldoftanksforumextendedstat.user.js/raw/tip/data/img/lang/"+s[y].u.lng+".png");
					flag.title = s[y].u.lng.toUpperCase()+" Client";
					if (wg.srv !== "ru") {
						cell.appendChild(flag);
					}
					cell.appendChild(elem("div", "stat", "<span class='stat-win'>"+colStat((s[y].u.bat > 0) ? s[y].u.win : 0,"wr",2,"%")+"</span><span class='stat-rat'>"+s[y].wn8+"</span"));
				}
			}
		}
	}
}

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

// wnefficiency handler
function wnHnd(resp) {
	locStorage("wnExpValues", resp, "set");
	locStorage("wnExpDate", Date.now(), "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);
		}
	});
}

// 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) {element.innerHTML = html;}
	if (type) {element.type = type;}
	if (src) {element.src = src;}
	return element;
}
}(window));