WoTStatScript - ForumsExtendedStat

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

目前為 2015-10-14 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name WoTStatScript - ForumsExtendedStat
  3. // @version 1.08.0
  4. // @description Adds stats and links for posts on official World of Tanks forums
  5. // @author Orrie
  6. // @contributor seriych
  7. // @namespace http://forum.worldoftanks.eu/index.php?/topic/263423-
  8. // @icon http://dl.dropboxusercontent.com/u/12497046/wot/projects/statscript/img/icon.png
  9. // @include /^http:\/\/forum\.worldoftanks\.(eu|com|ru|asia|kr)\/\S+(\/topic\/|\?showtopic=)/
  10. // @include /^http:\/\/forum\.worldoftanks\.(eu|com|ru|asia|kr)\/index\.php\?app=members&module=messaging&section=view&do=showConversation&topicID=\d+/
  11. // @include /^http:\/\/forum\.worldoftanks\.(eu|com|ru|asia|kr)\/index\.php\?\/forum/\S+/
  12. // @grant GM_xmlhttpRequest
  13. // @license MIT License
  14. // ==/UserScript==
  15. (function() {
  16. // global vars
  17. var d = document;
  18.  
  19. // get server info and webpage
  20. var wg = {host:d.location.host, href:d.location.href, clan:{}};
  21. wg.srv = d.location.host.match(/\.(eu|ru|com|asia|kr)/)[1];
  22. wg.topic = /(\/topic\/|\?showtopic=|messaging\&)/.test(wg.href);
  23. wg.forum = /\/forum\//.test(wg.href);
  24. wg.login = !!d.getElementsByClassName('js-cm-login-link')[0];
  25.  
  26. // server, API and cluster settings
  27. var sc = {
  28. vers: "1.08.0",
  29. host: "http://greasyfork.org/scripts/660-wotstatscript-forumsextendedstat",
  30. top: {
  31. eu: "http://forum.worldoftanks.eu/index.php?showtopic=263423",
  32. na: "http://forum.worldoftanks.com/index.php?showtopic=404652"
  33. },
  34. api: {
  35. ru: "98ca7c4fb108175b67d6505b9c3f3ebd",
  36. eu: "a7595640a90bf2d19065f3f2683b171c",
  37. com: "bf5dba0efd444d75147b6222dd903fd2",
  38. asia: "95f8713eccd322e52dbf521dbd28b19c",
  39. kr: "ffea0f1c3c5f770db09357d94fe6abfb"
  40. },
  41. sym: ",",
  42. wn: "http://www.wnefficiency.net/exp/expected_tank_values_latest.json"
  43. };
  44. // script threadlink
  45. 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>";
  46.  
  47. // external site support - wotlabs, noobmeter, wot-news, wotstats, wotcs, wot-life, wotstats.com.au and wotreplays
  48. var srv = {
  49. s: "en", wl: false, nm: false, vb: false, ws: false, wr: false, ct: false, wlf: false
  50. };
  51. switch(wg.srv) {
  52. case ("eu"): // eu server
  53. srv.wl = srv.nm = srv.vb = srv.ws = srv.wr = srv.ct = srv.wlf = wg.srv;
  54. break;
  55. case ("ru"): // ru server
  56. srv.wl = srv.nm = srv.vb = srv.ws = srv.wr = srv.ct = srv.wlf = wg.srv;
  57. srv.s = "ru";
  58. sc.sym = " ";
  59. break;
  60. case ("com"): // na server
  61. srv.wl = srv.nm = srv.vb = srv.ws = srv.ct = "na"; srv.wr = "com";
  62. break;
  63. case ("asia"): // asia server
  64. srv.wl = srv.nm = srv.vb = srv.ws = "sea"; srv.ct = wg.srv; srv.wr = "com";
  65. break;
  66. case ("kr"): // korean server
  67. srv.wl = srv.nm = srv.vb = srv.ws = srv.ct = srv.ch = wg.srv; srv.wr = "com";
  68. break;
  69. default: break;
  70. }
  71.  
  72. // data uri
  73. var uri = {
  74. icon_arrow:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPwAAAAJCAMAAAAhKrH/AAAAV1BMVEUAAAD///+TKCf9AQmTLiX9AQmTMir9AQmTLif9AQmTMSz9AQmTMir9AQmTMyn9AQmTMirvGgKTMirsIAGTMirwGQOTMiqTMirsIAGaNDGgNzfqJwDrJABtE0DNAAAAGnRSTlMAABERIiIzM0REVVVmZnd3iIqZmrvDzN3g7thzQuwAAACHSURBVHja5dVLDsIwDEXRCySlP0IMoXXs7H+dDBASA1bQ3B0cPclm2Fe2wrfTQeO3qwqqAKWek80HxfO/l1/EBRgtU2tf+KkJ7TO9hdVSV3jU42f6ZClY6Qt/d4n+BGol29jTwQN1pE2QbA610BVefImuwL7xsNAXXhVpEYY8kNfO/rwsyA3ekEsOT2YDLE8AAAAASUVORK5CYII=",
  75. q_mark: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAANCAYAAACgu+4kAAAAh0lEQVQoz2OwsbGxtre3jwTiBBJxJEgvA4jBQCYA6wWZhkVOFIjLgPgOEH8A4llArIDFgARcBsgCsRkQywGxLhC3AXEtKQYgA5DN6UCcRo4BEkCcDcSVQMxLqgHcQJwPxNVAzIMjEPEaIAXEJUCcgScWiAoDBnINEAbieiCuobkBlKVESvMCADnAReqxtj3zAAAAAElFTkSuQmCC"
  76. };
  77.  
  78. // fetch wnefficiency values - check if array exists in localStorage, otherwise fetch and reload page
  79. var statObj = [],
  80. wnExpValues = JSON.parse(localStorage.getItem("wnExpValues")),
  81. wnExpDate = JSON.parse(localStorage.getItem("wnExpDate"))+1728e5 >= Date.now(), // true if timestamp is less than 2 days old, refresh list if false.
  82. wnExpVers = JSON.parse(localStorage.getItem("wnExpVers")) || "";
  83. if (wnExpVers[0]==sc.vers && wnExpValues && wnExpDate) {
  84. statObj = wnExpValues.data;
  85. }
  86. else {
  87. reqHnd(sc.wn, wnHnd);
  88. }
  89.  
  90. // style contents
  91. var style = elem("style", "wotstatscript", "", "text/css"),
  92. styleText = [
  93. ".cm-menu__user > *:not(.cm-notifications) {display: inline-block}",
  94. ".b-scriptlink a {color: #E5B12E;}",
  95. ".b-scriptlink a:hover {color: #FFBE4C; text-shadow: 0px 0px 7px rgba(255, 126, 0, 0.7);}",
  96. ".b-login-msg:hover, .b-scriptlink:hover {color: #707273; cursor: initial;}",
  97. ".cm-link__get-gold {margin: 0 12px;}",
  98. ".author_info {min-height: 310px; z-index: 1;}",
  99. ".user_details > br {display: none;}",
  100. ".basic_info {margin: 0 0 4px;}",
  101. ".post_count.margin-bottom {margin: 0 0 5px;}",
  102. ".battles_count {display: none;}",
  103. ".i-xvm-lang {vertical-align: text-top;}",
  104. ".t-table-stats {margin: 5px 0; width: auto;}",
  105. ".t-table-stats td {padding: 0 5px 0 0; line-height: 16px;}",
  106. ".t-table-stats td:last-of-type {font-weight: bold;}",
  107. ".t-tables-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; margin: 5px 0 5px -3px; overflow: hidden; padding: 3px 3px 0; position: absolute; text-overflow: ellipsis; white-space: nowrap; height: 25px; width: 90px;}",
  108. ".t-tables-links:hover {border-color: #7D7D7D; height: auto; width: auto;}",
  109. ".t-tables-links tbody {display: table; width: 180px;}",
  110. ".t-tables-links td {padding: 0 0 2px; font-weight: bold;}",
  111. ".t-tables-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;}",
  112. ".t-tables-links td a:hover {background: url("+uri.icon_arrow+") no-repeat scroll -244px 2px rgba(0, 0, 0, 0);}",
  113. ".t-tables-links tr:last-of-type td {}",
  114. ".realm_kr .t-tables-links {width: 108px;}",
  115. ".realm_kr .t-tables-links:hover {width: 215px;}",
  116. ".realm_kr .t-tables-links tbody {width: 215px;}",
  117. ".topic_list {table-layout: auto}",
  118. ".col_f_stats {width: 200px;}",
  119. ".col_f_preview {width: 10px !important;}",
  120. ".col_f_views {width: auto;}",
  121. ".col_f_post {width: auto;}",
  122. ".col_f_stats .i-xvm-lang {margin: 6px 0 0 0;}",
  123. ".t-row-stats {float: right; table-layout: fixed; width: 175px;}",
  124. ".realm_ru .t-row-stats {width: 200px;}",
  125. "table.ipb_table .t-row-stats td {border-bottom: 0; font-size: 11px; padding: 0;}",
  126. "#announcements .t-row-stats td {border-bottom: 0;}",
  127. ".s-no-stats {color: #A03737; display: table; font-size: 14px; margin: 0 auto;}"
  128. ];
  129. style.textContent = styleText.join("");
  130. d.head.appendChild(style);
  131. // end style
  132.  
  133. // colour scale array
  134. var colArr = {
  135. // col wr bat wn8 wn7 eff nm pr
  136. sUni: [ "#5A3175", 65, 30000, 2900, 2050, 2050, 2000 ], // 99.99% super unicum
  137. uni: [ "#83579D", 60, 25000, 2450, 1850, 1800, 1950, 9930 ], // 99.90% unicum
  138. gr8: [ "#3972C6", 56, 21000, 2000, 1550, 1500, 1750, 8525 ], // 99.00% great
  139. vGud: [ "#4099BF", 54, 17000, 1600, 1350 ], // 95.00% very good
  140. good: [ "#4D7326", 52, 13000, 1200, 1100, 1200, 1450, 6340 ], // 82.00% good
  141. aAvg: [ "#849B24", 50, 10000, 900 ], // 63.00% above average
  142. avg: [ "#CCB800", 48, 7000, 650, 900, 900, 1250, 4185 ], // 40.00% average
  143. bAvg: [ "#CC7A00", 47, 3000, 450, 700, 600, 1150, 2020 ], // 20.00% below average
  144. bas: [ "#CD3333", 46, 1000, 300, 500 ], // 6.00% basic
  145. beg: [ "#930D0D", 0, 0, 0, 0, 0, 0, 0 ], // 0.00% beginner
  146. dft: [ "#6B6B6B" ], // default
  147. id: { "col": 0, "wr": 1, "bat": 2, "wn8": 3, "wn7": 4, "eff": 5, "nm": 6, "pr": 7 } // type identifier
  148. };
  149.  
  150. // localization
  151. var loc = [
  152. { en: "Client", ru: "Клиент"},
  153. { en: "Winrate:", ru: "Винрейт:"},
  154. { en: "Battles:", ru: "Боев:"},
  155. { en: "Rating:", ru: "Рейтинг:"},
  156. { en: "WN8:", ru: "WN8:"},
  157. { en: "Please Login for Stats", ru: "Please Login for Stats"},
  158. { en: "No Stats Found", ru: "No Stats Found"}
  159. //{ en: "f00_en", ru: "f00_ru"},
  160. ];
  161. // process localization
  162. for (var _l=0, l_len = loc.length; _l<l_len; _l++) {
  163. loc[_l] = loc[_l][srv.s];
  164. }
  165.  
  166.  
  167. // script link
  168. var clanHead_div = elem("div", "cm-parent-link b-scriptlink", sc.link),
  169. navService_class = d.getElementsByClassName('cm-menu')[1];
  170. navService_class.insertBefore(clanHead_div, navService_class.firstChild);
  171.  
  172. // formula calculations and variables
  173. // create global post variable
  174. var postObj = {
  175. post: d.querySelectorAll(".post_wrap, .post_wrap__wg"),
  176. span: d.querySelectorAll("span.desc.lighter.blend_links"),
  177. cls: [],
  178. ids: [],
  179. num: []
  180. },
  181. s = {};
  182. switch(true) {
  183. case (wg.topic):
  184. postObj.cls = postObj.post; break;
  185. case (wg.forum):
  186. postObj.cls = postObj.span; break;
  187. default: break;
  188. }
  189.  
  190. // fetch userids and store all posts into one obj for later use
  191. if (wg.topic || (wg.forum && wg.login === false)) {
  192. for (var _t=0, _t_len = postObj.cls.length; _t<_t_len; _t++) {
  193. var id;
  194. switch(true) {
  195. case (wg.topic):
  196. id = postObj.post[_t].getElementsByClassName("ipsUserPhotoLink")[0].getAttribute('href').match(/\-(\d+)\//)[1]; break;
  197. case (wg.forum):
  198. var id_url = postObj.span[_t].getElementsByClassName("url")[0];
  199. if (id_url) {
  200. id = id_url.getAttribute('href').match(/\-(\d+)\//)[1];
  201. }
  202. break;
  203. default: break;
  204. }
  205. if (!isNaN(id)) {
  206. var users = postObj.ids.length,
  207. index = postObj.ids.indexOf(id);
  208. s[id] = {u:{},v:{frag:0,dmg:0,spot:0,def:0,win:0},wn8:""};
  209. if (index>-1) {
  210. postObj.num[index][postObj.num[index].length] = _t;
  211. }
  212. else {
  213. postObj.ids[users] = id;
  214. postObj.num[users] = [_t];
  215. }
  216. }
  217. }
  218. }
  219. else {
  220. navService_class.insertBefore(elem("div", "cm-parent-link b-login-msg", "<div>"+loc[5]+"</div>"), navService_class.firstChild);
  221. }
  222.  
  223. // request and retrieve statistics from API
  224. if (postObj.ids.length > 0) {
  225. sc.api.i = "http://api.worldoftanks."+wg.srv+"/wot/account/info/?application_id="+sc.api[wg.srv]+"&account_id="+postObj.ids.join(',');
  226. sc.api.v = "http://api.worldoftanks."+wg.srv+"/wot/account/tanks/?application_id="+sc.api[wg.srv]+"&account_id="+postObj.ids.join(',');
  227. reqHnd(sc.api.i, apiInfoHnd);
  228. }
  229. else {
  230. console.error("No post IDs found or not logged in");
  231. }
  232.  
  233. // processing information from player API
  234. function apiInfoHnd(resp) {
  235. var data = JSON.parse(resp).data;
  236. for (var a in data) {
  237. if (data.hasOwnProperty(a)) {
  238. var pData = data[a];
  239. if (pData !== null) {
  240. // store stats
  241. var pDataStats = pData.statistics.all;
  242. s[pData.account_id].u = {
  243. name: pData.nickname,
  244. id: pData.account_id,
  245. cid: pData.clan_id,
  246. bat: pDataStats.battles,
  247. win: (pDataStats.wins/pDataStats.battles)*100,
  248. dmg: pDataStats.damage_dealt/pDataStats.battles,
  249. frag: pDataStats.frags/pDataStats.battles,
  250. spot: pDataStats.spotted/pDataStats.battles,
  251. def: pDataStats.dropped_capture_points/pDataStats.battles,
  252. wgr: pData.global_rating,
  253. lng: pData.client_language
  254. };
  255. }
  256. else {
  257. // store stats
  258. s[parseFloat(a)].u = {
  259. bat: 0
  260. };
  261. }
  262. }
  263. }
  264. reqHnd(sc.api.v, apiVehHnd);
  265. }
  266.  
  267. // processing information from vehicle API and calculate WN8
  268. function apiVehHnd(resp) {
  269. var data = JSON.parse(resp).data;
  270. for (var p in data) {
  271. if (data.hasOwnProperty(p)) {
  272. var vData = data[p];
  273. if (vData !== null) {
  274. var rWin, rDmg, rFrag, rSpot, rDef;
  275. if (s[p].u.bat > 0) {
  276. for (var v in vData) {
  277. if (vData.hasOwnProperty(v)) {
  278. for (var _so=0, _so_len = statObj.length; _so<_so_len; _so++) {
  279. if (statObj[_so].IDNum == vData[v].tank_id) {
  280. var vehStat = statObj[_so],
  281. dataBattles = vData[v].statistics.battles;
  282. s[p].v.frag += vehStat.expFrag * dataBattles;
  283. s[p].v.dmg += vehStat.expDamage * dataBattles;
  284. s[p].v.spot += vehStat.expSpot * dataBattles;
  285. s[p].v.def += vehStat.expDef * dataBattles;
  286. s[p].v.win += vehStat.expWinRate * dataBattles;
  287. break;
  288. }
  289. }
  290. }
  291. }
  292. rWin = Math.max(((s[p].u.win /(s[p].v.win /s[p].u.bat)-0.71)/(1-0.71)),0);
  293. rDmg = Math.max(((s[p].u.dmg /(s[p].v.dmg /s[p].u.bat)-0.22)/(1-0.22)),0);
  294. 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);
  295. 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);
  296. 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);
  297. s[p].wn8 = colStat(980*rDmg + 210*rDmg*rFrag + 155*rFrag*rSpot + 75*rDef*rFrag + 145*Math.min(1.8,rWin),"wn8",0);
  298. }
  299. else {
  300. s[p].wn8 = colStat(0,"wn8",0);
  301. }
  302. }
  303. }
  304. }
  305. statInsert();
  306. }
  307.  
  308. // insert stats and links to every post
  309. function statInsert() {
  310. for (var y in s) {
  311. if (s.hasOwnProperty(y)) {
  312. var iPost = postObj.ids.indexOf(y), flag;
  313. if (iPost >- 1 && s[y].u.id) {
  314. if (wg.topic) {
  315. var userStats = [
  316. "<td>"+loc[1]+"</td><td>"+colStat((s[y].u.bat > 0) ? s[y].u.win : 0,"wr",2,"%")+"</td>",
  317. "<td>"+loc[2]+"</td><td>"+colStat(s[y].u.bat,"bat",0,"")+"</td>",
  318. "<td>"+loc[3]+"</td><td>"+colStat(s[y].u.wgr,"pr",0,"")+"</td>",
  319. "<td>"+loc[4]+"</td><td>"+s[y].wn8+"</td>"
  320. ],
  321. userLinks = [
  322. [
  323. ["<a target='_blank' href='http://worldoftanks."+wg.srv+"/community/accounts/"+s[y].u.id+"-"+s[y].u.name+"/'>Player Profile</a>"],
  324. [srv.wl, "<a target='_blank' href='http://wotlabs.net/"+srv.wl+"/player/"+s[y].u.name+"'>WoTLabs</a>"]
  325. ],
  326. [
  327. [srv.vb, "<a target='_blank' href='http://vbaddict.net/player/"+s[y].u.name.toLowerCase()+"-"+srv.vb+"'>vBAddict</a>"],
  328. [srv.nm, "<a target='_blank' href='http://noobmeter.com/player/"+srv.nm+"/"+s[y].u.name+"'>Noobmeter</a>"]
  329. ],
  330. [
  331. [srv.ws, "<a target='_blank' href='http://wotstats.org/stats/"+srv.ws+"/"+s[y].u.name+"/'>WoTstats</a>"],
  332. [srv.ct, "<a target='_blank' href='http://clantools.us/servers/"+srv.ct+"/players?id="+s[y].u.id+"'>Clan Tools</a>"]
  333. ],
  334. [
  335. [srv.wr, "<a target='_blank' href='http://wotreplays."+srv.wr+"/player/"+s[y].u.name+"'>WoTReplays</a>"],
  336. (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>"]
  337. ]
  338. ];
  339. for (var _i=0, _i_len = postObj.num[iPost].length; _i<_i_len; _i++) {
  340. var groupTitle = postObj.post[postObj.num[iPost][_i]].getElementsByClassName("group_title")[0],
  341. basicInfo = postObj.post[postObj.num[iPost][_i]].getElementsByClassName("basic_info")[0],
  342. infoClass = postObj.post[postObj.num[iPost][_i]].getElementsByClassName("author_info")[0],
  343. statTable = elem("table", "t-table-stats", ""),
  344. urlTable = elem("table", "t-tables-links", "<tbody></tbody>");
  345. flag = elem("img", "i-xvm-lang", "", "", "https://bytebucket.org/seriych/worldoftanksforumextendedstat.user.js/raw/tip/data/img/lang/"+s[y].u.lng+".png");
  346. for (var _sr=0, _sr_len = userStats.length; _sr<_sr_len; ++_sr) {
  347. statTable.appendChild(elem("tr", "", userStats[_sr]));
  348. }
  349. for (var _l=0, _l_len = userLinks.length; _l<_l_len; ++_l) {
  350. var uRow = elem("tr", "", "");
  351. for (var _lr=0, _lr_len = userLinks[_l].length; _lr<_lr_len; ++_lr) {
  352. uRow.appendChild((userLinks[_l][_lr][0] && userLinks[_l][_lr][1]) ? elem("td", "", userLinks[_l][_lr][1]) : elem("td", "", userLinks[_l][_lr][0]));
  353. }
  354. urlTable.firstElementChild.appendChild(uRow);
  355. }
  356. if (wg.srv !== "ru") {
  357. groupTitle.appendChild(flag);
  358. }
  359. flag.title = s[y].u.lng.toUpperCase()+" "+loc[0];
  360. flag.addEventListener('error', function(){this.src=uri.q_mark;});
  361. basicInfo.insertBefore(statTable, basicInfo.lastElementChild);
  362. infoClass.appendChild(urlTable);
  363. }
  364. }
  365. else if (wg.forum) {
  366. for (var _r=0, _r_len = postObj.num[iPost].length; _r<_r_len; _r++) {
  367. var id_url = postObj.span[postObj.num[iPost][_r]].getElementsByClassName("url")[0],
  368. threadRow = postObj.span[postObj.num[iPost][_r]].parentNode.parentNode,
  369. threadRowClsList = threadRow.classList;
  370. if (threadRowClsList.contains("announcement")) {
  371. statCell = threadRow.insertCell(1);
  372. }
  373. else if (threadRowClsList.contains("__topic")) {
  374. statCell = threadRow.insertCell(3);
  375. }
  376. statCell.className = "col_f_stats";
  377. if (!id_url || s[y].u.bat === 0) {
  378. statCell.appendChild(elem("span", "s-no-stats", loc[6]));
  379. }
  380. else {
  381. var statsRow = [
  382. "<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>",
  383. "<td>"+loc[3]+"</td><td>"+colStat(s[y].u.wgr,"pr",0,"")+"</td><td>"+loc[4]+"</td><td>"+s[y].wn8+"</td>",
  384. ], statCell,
  385. rowTable = elem("table", "t-row-stats", "");
  386. flag = elem("img", "i-xvm-lang", "", "", "https://bytebucket.org/seriych/worldoftanksforumextendedstat.user.js/raw/tip/data/img/lang/"+s[y].u.lng+".png");
  387. for (var _rr=0, _rr_len = statsRow.length; _rr<_rr_len; ++_rr) {
  388. rowTable.appendChild(elem("tr", "", statsRow[_rr]));
  389. }
  390. if (wg.srv !== "ru") {
  391. statCell.appendChild(flag);
  392. }
  393. flag.title = s[y].u.lng.toUpperCase()+" "+loc[0];
  394. flag.addEventListener('error', function(){this.src=uri.q_mark;});
  395. statCell.appendChild(rowTable);
  396. }
  397. }
  398. }
  399. }
  400. }
  401. }
  402. }
  403.  
  404. // wnefficiency handler
  405. function wnHnd(resp) {
  406. localStorage.setItem("wnExpValues", resp);
  407. localStorage.setItem("wnExpDate", Date.now());
  408. localStorage.setItem("wnExpVers", JSON.stringify([sc.vers, JSON.parse(resp).header.version]));
  409. location.reload();
  410. }
  411. // end wnefficiency handler
  412.  
  413. // request handler
  414. function reqHnd(url, handler) {
  415. GM_xmlhttpRequest({
  416. method: "GET",
  417. url: url,
  418. onload: function(resp) {
  419. handler(resp.responseText);
  420. }
  421. });
  422. }
  423.  
  424. // colouring
  425. function colStat(input, type, dec, sym) {
  426. var color = colArr.dft[0],
  427. output = input.toFixed(dec);
  428. if (sym) {
  429. output += sym;
  430. }
  431. if (input >= 1000) {
  432. output = input.toFixed(dec).toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1"+sc.sym);
  433. }
  434. for (var c in colArr) {
  435. if (colArr.hasOwnProperty(c)) {
  436. if (input >= colArr[c][colArr.id[type]]) {
  437. color = colArr[c][0]; break;
  438. }
  439. }
  440. }
  441. return "<font color='"+color+"'>"+output+"</font>";
  442. }
  443.  
  444. // quick creation of element
  445. function elem(tag, name, html, type, src) {
  446. var element = d.createElement(tag);
  447. if (name) {element.className = name;}
  448. if (html) {element.innerHTML = html;}
  449. if (type) {element.type = type;}
  450. if (src) {element.src = src;}
  451. return element;
  452. }
  453. }(window));