Greasy Fork

Greasy Fork is available in English.

WoTStatScript - Tournament Teams

More info for World of Tanks tournament teams

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

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