WoTStatScript - Tournament Teams

More info for World of Tanks tournament teams

  1. // ==UserScript==
  2. // @name WoTStatScript - Tournament Teams
  3. // @version 0.9.20.0.1
  4. // @description More info for World of Tanks tournament teams
  5. // @author Orrie
  6. // @namespace http://forum.worldoftanks.eu/index.php?/topic/263423-
  7. // @icon https://i.imgur.com/AxOhQ7C.png
  8. // @include http*://worldoftanks.eu/*/tournaments/*/team/*
  9. // @include http*://worldoftanks.com/*/tournaments/*/team/*
  10. // @include http*://worldoftanks.ru/*/tournaments/*/team/*
  11. // @include http*://worldoftanks.asia/*/tournaments/*/team/*
  12. // @include http*://worldoftanks.kr/*/tournaments/*/team/*
  13. // @grant GM_xmlhttpRequest
  14. // @grant GM.xmlHttpRequest
  15. // @connect api.worldoftanks.eu
  16. // @connect api.worldoftanks.ru
  17. // @connect api.worldoftanks.com
  18. // @connect api.worldoftanks.asia
  19. // @connect api.worldoftanks.kr
  20. // @connect www.wnefficiency.net
  21. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
  22. // @license MIT License
  23. // ==/UserScript==
  24. (function () {
  25. // global vars
  26. var d = document, c = d.cookie;
  27.  
  28. // get server info and webpage
  29. var wg = {
  30. srv: d.location.host.match(/\.(eu|ru|com|asia|kr)/)[1]
  31. };
  32.  
  33. // server, API and cluster settings
  34. var sc = {
  35. vers: ((GM_info) ? GM_info.script.version : ""),
  36. host: "https://greasyfork.org/en/scripts/13064-wotstatscript-tournament-teams",
  37. user: {
  38. wl: "https://forum.wotlabs.net/index.php?/user/1618-orrie/",
  39. wot: "https://worldoftanks.eu/community/accounts/505838943-Orrie/"
  40. },
  41. top: {
  42. eu: "https://forum.worldoftanks.eu/index.php?showtopic=263423",
  43. na: "https://forum.worldoftanks.com/index.php?showtopic=404652"
  44. },
  45. cred: { // translators
  46. cs: "<tr><td><a class='b-orange-arrow' href='https://worldoftanks.eu/community/accounts/500744969/'>Crabtr33</a></td><td><a class='b-orange-arrow' href='https://worldoftanks.eu/community/accounts/508323506/'>Ragnarocek</a></td></tr><tr><td><a class='b-orange-arrow' href='https://worldoftanks.eu/community/accounts/508904714/'>jViks</a></td></tr>" ,
  47. de: "<tr><td><a class='b-orange-arrow' href='https://worldoftanks.eu/community/accounts/504873051/'>ArtiOpa</a></td><td><a class='b-orange-arrow' href='https://worldoftanks.eu/community/accounts/501118529/'>Crakker</a></td></tr><tr><td><a class='b-orange-arrow' href='https://worldoftanks.eu/community/accounts/501072645/'>multimill</a></td><td><a class='b-orange-arrow' href='https://worldoftanks.eu/community/accounts/500373105/'>coolathlon</a></td></tr>",
  48. fr: "<tr><td><a class='b-orange-arrow' href='https://worldoftanks.eu/community/accounts/506641783/'>SuperPommeDeTerre</a></td></tr>",
  49. pl: "<tr><td><a class='b-orange-arrow' href='https://worldoftanks.eu/community/accounts/501801562/'>KeluMocy</a></td><td><a class='b-orange-arrow' href='https://worldoftanks.eu/community/accounts/504412736/'>pokapokami</a></td></tr>",
  50. es: "<tr><td><a class='b-orange-arrow' href='https://worldoftanks.eu/community/accounts/512759883/'>Frodo45127</a></td></tr>",
  51. tr: "<tr><td><a class='b-orange-arrow' href='https://worldoftanks.eu/community/accounts/500400806/'>Ufuko</a></td></tr>",
  52. ru: "<tr><td><a class='b-orange-arrow' href='https://worldoftanks.ru/community/accounts/291063/'>Bananium</a></td><td><a class='b-orange-arrow' href='https://worldoftanks.ru/community/accounts/147060/'>Minamoto</a></td></tr>"
  53. },
  54. api: {
  55. wg_key: "a7595640a90bf2d19065f3f2683b171c"
  56. },
  57. wn: "https://static.modxvm.com/wn8-data-exp/json/wn8exp.json",
  58. col: {
  59. // col wr wgr wn8
  60. sUni: [ "#5A3175", 65, 9900, 2900 ], // 99.99% super unicum
  61. uni: [ "#83579D", 60, 9000, 2450 ], // 99.90% unicum
  62. gr8: [ "#3972C6", 56, 8500, 2000 ], // 99.00% great
  63. vGud: [ "#4099BF", 54, 6500, 1600 ], // 95.00% very good
  64. good: [ "#4D7326", 52, 5000, 1200 ], // 82.00% good
  65. aAvg: [ "#849B24", 50, 4000, 900 ], // 63.00% above average
  66. avg: [ "#CCB800", 48, 3000, 650 ], // 40.00% average
  67. bAvg: [ "#CC7A00", 47, 2000, 450 ], // 20.00% below average
  68. bas: [ "#CD3333", 46, 1500, 300 ], // 6.00% basic
  69. beg: [ "#930D0D", 0, 0, 0 ], // 0.00% beginner
  70. dft: [ "#6B6B6B" ], // default
  71. id: { col: 0, wr: 1, wgr: 2, wn8: 3 } // type identifier
  72. },
  73. loc: c.match(/hllang=(\w+)/)[1],
  74. locSup: ["en", "ru", "cs", "de", "fr", "pl", "es", "tr"],
  75. date: Date.now(),
  76. debug: false
  77. };
  78.  
  79. // script functions
  80. var sf = {
  81. tableFetch: function () {
  82. teamObj.cls = d.getElementsByClassName("tournament-table_team");
  83. for (var _t=0, _t_len = teamObj.cls.length; _t<_t_len; _t++) {
  84. if (teamObj.cls[_t]) {
  85. var id = teamObj.cls[_t].getAttribute('href').match(/\/(\d+)\-/)[1];
  86. if (!isNaN(id)) {
  87. teamObj.cls[_t].parentNode.parentNode.id = id;
  88. teamObj.ids.push(id);
  89. s.user[id] = {u:{},v:{frag:0,dmg:0,spot:0,def:0,win:0},wn8:""};
  90. }
  91. }
  92. }
  93. s.team = {wn8:0, win:0, tbBat:0, tbWin:0, mem: teamObj.ids.length};
  94. // request and retrieve statistics from API
  95. if (teamObj.ids.length > 0) {
  96. sc.api.i = "https://api.worldoftanks."+wg.srv+"/wot/account/info/?application_id="+sc.api.wg_key+"&account_id="+teamObj.ids.join(',');
  97. sc.api.v = "https://api.worldoftanks."+wg.srv+"/wot/account/tanks/?application_id="+sc.api.wg_key+"&account_id="+teamObj.ids.join(',');
  98. sf.request("infoData", sc.api.i, sf.apiInfoHnd);
  99. }
  100. else {
  101. console.error("No post IDs found or not logged in");
  102. }
  103. },
  104. apiInfoHnd: function (resp) { // processing information from player API
  105. var data = resp.data;
  106. for (var a in data) {
  107. if (data.hasOwnProperty(a)) {
  108. var pData = data[a];
  109. if (pData !== null) {
  110. // store stats
  111. var pDataStats = pData.statistics.all,
  112. pDataStatsTB = pData.statistics.team,
  113. userID = pData.account_id;
  114. s.user[userID].u = {
  115. name: pData.nickname,
  116. id: userID,
  117. cid: pData.clan_id,
  118. bat: pDataStats.battles,
  119. win: (pDataStats.wins/pDataStats.battles)*100,
  120. dmg: pDataStats.damage_dealt/pDataStats.battles,
  121. frag: pDataStats.frags/pDataStats.battles,
  122. spot: pDataStats.spotted/pDataStats.battles,
  123. def: pDataStats.dropped_capture_points/pDataStats.battles,
  124. tbBat: pDataStatsTB.battles,
  125. tbWin: (pDataStatsTB.wins/pDataStatsTB.battles)*100,
  126. wgr: pData.global_rating,
  127. lng: pData.client_language
  128. };
  129. s.team.win += (!isNaN(s.user[userID].u.win)) ? s.user[userID].u.win : 0;
  130. s.team.tbBat += (!isNaN(s.user[userID].u.tbBat)) ? s.user[userID].u.tbBat : 0;
  131. s.team.tbWin += (!isNaN(s.user[userID].u.tbWin)) ? s.user[userID].u.tbWin : 0;
  132. }
  133. }
  134. }
  135. sf.request("vehData", sc.api.v, sf.apiVehHnd);
  136. },
  137. apiVehHnd: function (resp) { // processing information from vehicle API and calculate WN8
  138. var data = resp.data;
  139. for (var p in data) {
  140. if (data.hasOwnProperty(p)) {
  141. var vData = data[p];
  142. if (vData !== null) {
  143. var rWin, rDmg, rFrag, rSpot, rDef, wn8 = 0, battles = 0;
  144. if (s.user[p].u.bat > 0) {
  145. for (var v in vData) {
  146. if (vData.hasOwnProperty(v)) {
  147. for (var _so=0, _so_len = wn.stat.length; _so<_so_len; _so++) {
  148. if (wn.stat[_so].IDNum == vData[v].tank_id) {
  149. var vehStat = wn.stat[_so],
  150. dataBattles = vData[v].statistics.battles;
  151. s.user[p].v.frag += vehStat.expFrag * dataBattles;
  152. s.user[p].v.dmg += vehStat.expDamage * dataBattles;
  153. s.user[p].v.spot += vehStat.expSpot * dataBattles;
  154. s.user[p].v.def += vehStat.expDef * dataBattles;
  155. s.user[p].v.win += vehStat.expWinRate * dataBattles;
  156. battles += dataBattles;
  157. break;
  158. }
  159. }
  160. }
  161. }
  162. rWin = Math.max(((s.user[p].u.win /(s.user[p].v.win /battles)-0.71)/(1-0.71)),0);
  163. rDmg = Math.max(((s.user[p].u.dmg /(s.user[p].v.dmg /battles)-0.22)/(1-0.22)),0);
  164. rFrag = Math.max(Math.min(rDmg+0.2,((s.user[p].u.frag/(s.user[p].v.frag/battles)-0.12)/(1-0.12))),0);
  165. rSpot = Math.max(Math.min(rDmg+0.1,((s.user[p].u.spot/(s.user[p].v.spot/battles)-0.38)/(1-0.38))),0);
  166. rDef = Math.max(Math.min(rDmg+0.1,((s.user[p].u.def /(s.user[p].v.def /battles)-0.10)/(1-0.10))),0);
  167. wn8 = 980*rDmg + 210*rDmg*rFrag + 155*rFrag*rSpot + 75*rDef*rFrag + 145*Math.min(1.8,rWin);
  168. }
  169. // store wn8 and add to clan total
  170. s.user[p].wn8 = sf.color(wn8,"wn8",0);
  171. s.team.wn8 += wn8;
  172. }
  173. }
  174. }
  175. // calculate average wn8 / winrate
  176. s.team.wn8 = s.team.wn8/s.team.mem;
  177. s.team.win = s.team.win/s.team.mem;
  178. s.team.tbBat = s.team.tbBat/s.team.mem;
  179. s.team.tbWin = s.team.tbWin/s.team.mem;
  180. sf.statInsert();
  181. },
  182. statInsert: function () { // insert stats and links to every post
  183. var teamWrpr = d.getElementById("team_management"),
  184. teamHead = d.getElementsByClassName("tournament-table_tr")[0];
  185. teamWrpr.insertBefore(sf.elem("div", "b-stat-total", "<span><span>WN8:</span>"+sf.color(s.team.wn8,"wn8",0)+"</span><span><span>WR:</span>"+sf.color(s.team.win,"wr",2,"%")+"</span><span><span>TB-WR:</span>"+sf.color(s.team.tbWin,"wr",2,"%")+"</span><span><span>TB-"+loc[5]+":</span>"+sf.color(s.team.tbBat,"bats",0)+"</span>"), teamWrpr.firstElementChild.nextSibling);
  186. teamHead.cells[0].parentNode.insertBefore(sf.elem("th", "tournament-table_th th-stats", "WN8"), teamHead.cells[0].nextSibling);
  187. teamHead.cells[1].parentNode.insertBefore(sf.elem("th", "tournament-table_th th-stats", "WR"), teamHead.cells[1].nextSibling);
  188. teamHead.cells[2].parentNode.insertBefore(sf.elem("th", "tournament-table_th th-stats", "TB-WR"), teamHead.cells[2].nextSibling);
  189. teamHead.cells[3].parentNode.insertBefore(sf.elem("th", "tournament-table_th th-stats", "TB-Battles"), teamHead.cells[3].nextSibling);
  190. for (var y in s.user) {
  191. if (s.user.hasOwnProperty(y)) {
  192. var userCheck = teamObj.ids.indexOf(y);
  193. if (userCheck >- 1) {
  194. var row = d.getElementById(y),
  195. infoFlag = sf.elem("img", "i-xvm-lang", "", "", "https://bytebucket.org/seriych/worldoftanksforumextendedstat.user.js/raw/tip/data/img/lang/"+s.user[y].u.lng+".png");
  196. infoFlag.title = s.user[y].u.lng.toUpperCase()+" Client";
  197. row.cells[0].appendChild(infoFlag);
  198. row.cells[0].parentNode.insertBefore(sf.elem("td", "tournament-table_td td-stats", "<span class='b-player-stat'>"+s.user[y].wn8+"</span>"), row.cells[0].nextSibling);
  199. row.cells[1].parentNode.insertBefore(sf.elem("td", "tournament-table_td td-stats", "<span class='b-player-stat'>"+sf.color((s.user[y].u.bat > 0) ? s.user[y].u.win : 0,"wr",2,"%")+"</span>"), row.cells[1].nextSibling);
  200. row.cells[2].parentNode.insertBefore(sf.elem("td", "tournament-table_td td-stats", "<span class='b-player-stat'>"+sf.color((s.user[y].u.tbBat > 0) ? s.user[y].u.tbWin : 0,"wr",2,"%")+"</span>"), row.cells[2].nextSibling);
  201. row.cells[3].parentNode.insertBefore(sf.elem("td", "tournament-table_td td-stats", "<span class='b-player-stat'>"+sf.color(s.user[y].u.tbBat,"bats",0)+"</span>"), row.cells[3].nextSibling);
  202. row.cells[5].innerHTML = "<span class='b-player-stat'>"+sf.color(s.user[y].u.wgr,"wgr",0)+"</span>";
  203. }
  204. }
  205. }
  206. // hide animated loading gear
  207. loadGif.classList.add("js-hidden");
  208. // remove dynamic table width
  209. var teamTable = d.getElementsByClassName("tournament-table")[0];
  210. teamTable.appendChild(teamTable.firstElementChild.cloneNode(true));
  211. teamTable.removeChild(teamTable.firstElementChild);
  212. },
  213. color: function (input, type, dec, sym) { // color formatting
  214. var color = sc.col.dft[0],
  215. output = input.toFixed(dec);
  216. if (sym) {
  217. output += sym;
  218. }
  219. if (input >= 1000) {
  220. output = input.toFixed(dec).toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1"+loc[0]);
  221. }
  222. for (var c in sc.col) {
  223. if (sc.col.hasOwnProperty(c)) {
  224. if (input >= sc.col[c][sc.col.id[type]]) {
  225. color = sc.col[c][0]; break;
  226. }
  227. }
  228. }
  229. return "<font color='"+color+"'>"+output+"</font>";
  230. },
  231. elem: function (tag, name, html, type, src) { // element creation
  232. var element = d.createElement(tag);
  233. if (name) {element.className = name;}
  234. if (html) {
  235. if (/</.test(html)) {
  236. element.innerHTML = html;
  237. }
  238. else {
  239. element.textContent = html;
  240. }
  241. }
  242. if (type) {element.type = type;}
  243. if (src) {element.src = src;}
  244. return element;
  245. },
  246. settings: function (name, text) { // script menu handler
  247. var setItem = sf.elem("li", "b-settingItem"),
  248. setDiv = sf.elem("div", "b-settingParent b-"+name, "<a>"+text+"</a>");
  249. switch(name) {
  250. case ("wnRefresh"):
  251. setDiv.addEventListener('click', function() {localStorage.removeItem("wnExpValues"); location.reload();}, false);
  252. break;
  253. default: break;
  254. }
  255. setItem.appendChild(setDiv);
  256. return setItem;
  257. },
  258. links: function (parent, links, type) { // statistic links handler
  259. var linksFragment = d.createDocumentFragment();
  260. for (var _l=0, _l_len = links.length; _l<_l_len; ++_l) {
  261. switch(type) {
  262. case ("table"):
  263. var link = sf.elem("tr");
  264. for (var _lr=0, _lr_len = links[_l].length; _lr<_lr_len; ++_lr) {
  265. link.appendChild((links[_l][_lr][0] && links[_l][_lr][1]) ? sf.elem("td", "", links[_l][_lr][1]) : sf.elem("td", "", links[_l][_lr][0]));
  266. }
  267. linksFragment.appendChild(link);
  268. break;
  269. case ("list"):
  270. if (links[_l] instanceof HTMLElement) {
  271. linksFragment.appendChild(links[_l]);
  272. }
  273. else {
  274. linksFragment.appendChild((links[_l][0] && links[_l][1]) ? sf.elem("li", "", links[_l][1]) : sf.elem("li", "statname", links[_l][0]));
  275. }
  276. break;
  277. default: break;
  278. }
  279. }
  280. parent.appendChild(linksFragment);
  281. },
  282. storage: function (name, data, type, mode) { // localstorage handler
  283. var storage;
  284. switch(type) {
  285. case ("set"):
  286. if (mode == "string") {
  287. data = JSON.stringify(data);
  288. }
  289. storage = localStorage.setItem(name, data);
  290. break;
  291. case ("get"):
  292. storage = localStorage.getItem(name);
  293. if (mode == "parse") {
  294. storage = JSON.parse(storage);
  295. }
  296. break;
  297. default: break;
  298. }
  299. return storage;
  300. },
  301. wn: function (resp) { // wnefficiency handler
  302. sf.storage("wnExpValues", resp, "set", "string");
  303. sf.storage("wnExpDate", sc.date, "set");
  304. sf.storage("wnExpVers", sc.vers, "set");
  305. location.reload();
  306. },
  307. request: function (name, url, handler) { // request handler
  308. GM.xmlHttpRequest({
  309. method: "GET",
  310. url: url,
  311. headers: {
  312. "Accept": "application/json"
  313. },
  314. onload: function(resp) {
  315. var data = JSON.parse(resp.responseText);
  316. if (resp.status == 200) {
  317. if (sc.debug) {console.info(name, data);}
  318. handler(data);
  319. }
  320. else {
  321. console.error("Error accessing", url, resp);
  322. }
  323. },
  324. onerror: function(resp) {
  325. console.error("Error accessing", url, resp);
  326. }
  327. });
  328. }
  329. };
  330.  
  331. // style contents
  332. var style = sf.elem("style", "wotstatscript", "", "text/css"),
  333. styleText = [
  334. // settings menu rules
  335. "#common_menu .menu-settings {color: #7C7E80; display: inline-block;}",
  336. "#common_menu .menu-settings .cm-user-menu-link {margin: 0 10px 0 0;}",
  337. "#common_menu .menu-settings .cm-user-menu-link_cutted-text {max-width: unset;}",
  338. "#common_menu .menu-settings .cm-user-menu {min-width: 200px; padding: 15px;}",
  339. "#common_menu .menu-settings .cm-parent-link:hover {cursor: pointer;}",
  340. "#common_menu .menu-settings .b-settingItem {margin: 6px 0px; text-align: center;}",
  341. "#common_menu .menu-settings label {display: table; line-height: normal; cursor: pointer; margin: 0 auto;}",
  342. "#common_menu .menu-settings .l-box {display: none;}",
  343. "#common_menu .menu-settings .b-checkbox {height: 16px; width: 16px; float: left; margin-right: 5px;}",
  344. "#common_menu .menu-settings .b-checkbox span {height: 16px; width: 16px;}",
  345. "#common_menu .menu-settings .b-combobox-label__checked {color: #DCDCDC;}",
  346. "#common_menu .menu-settings .b-settingItem .b-combobox-label:hover {color: #DCDCDC;}",
  347. "#common_menu .menu-settings .b-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);}",
  348. "#common_menu .menu-settings .b-settingItem .b-combobox-label:hover .b-checkbox.b-checkbox__checked {background-position: 0px -68px;}",
  349. "#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;}",
  350. "#common_menu .menu-settings textarea::-webkit-input-placeholder {color: #FFFFFF;}",
  351. "#common_menu .menu-settings textarea::-moz-placeholder {color: #FFFFFF;}",
  352. "#common_menu .menu-settings .b-settingParent {line-height: 26px;}",
  353. "#common_menu .menu-settings .b-settingParent a {cursor: pointer; color: #B1B2B3; text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.5);}",
  354. "#common_menu .menu-settings .b-settingParent a:hover {color: #FFFFFF; text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.75); text-decoration: underline;}",
  355. "#common_menu .menu-settings .settingCredits {margin: 2px 0px;}",
  356. "#common_menu .menu-settings .settingCredits h1 {color: #B1B2B3;}",
  357. "#common_menu .menu-settings .settingCredits table {font-size: 12px; margin: 0 auto; width: unset;}",
  358. "#common_menu .menu-settings .settingCredits table td {padding: 0 5px;}",
  359. "#common_menu .menu-settings .settingCredits p {font-size: 12px; padding: 2px 0;}",
  360. "#common_menu .menu-settings .settingCredits .b-orange-arrow {color: #F25322; line-height: 14px; padding-right: 9px;}",
  361. "#common_menu .menu-settings .settingCredits .b-orange-arrow:hover {color: #FF7432;}",
  362. "#common_menu .menu-settings .settingCredits.settingSeperator {border-top: 1px dashed #212123; margin-top: 6px; padding-top: 12px;}",
  363. "#common_menu .menu-settings .settingCredits.settingLinks a {margin: 0 5px;}",
  364. // processing loader rules
  365. ".processing {width: 100%; height: 100%; position: fixed; top: 0; left: 0; z-index: 500; background: url(https://eu.wargaming.net/clans/static/2.2.9/images/processing/processing_overlay-pattern.png);}",
  366. ".processing_loader {width: 56px; height: 54px; position: absolute; top: 50%; left: 50%; margin-top: -27px; margin-left: -28px;}",
  367. // team main rules
  368. ".tournament-heading {display: inline-block;}",
  369. ".b-stat-total {display: inline-block; position: absolute; left: 35%;}",
  370. ".b-stat-total span {font-size: 20px; margin: 0 10px;}",
  371. ".b-stat-total span span {color: #E9E2Bf; font-weight: 400; margin: 0 5px;}",
  372. // member table rules
  373. ".tournament-table th:first-child .tournament-table_ico-holder, .tournament-table th:first-child .tournament-table_heading-text {float: left;}",
  374. ".b-stat-head {float: right;}",
  375. ".b-stat-head span {font-size: 12px;}",
  376. ".b-stat-head span:first-of-type {margin: 0 20px;}",
  377. ".b-stat-head span:last-of-type {margin: 0 34px;}",
  378. ".tournament-table_th.th-stats {width: 100px; text-align: center;}",
  379. ".tournament-table_td {padding: 8px 2%;}",
  380. ".tournament-table_td.td-stats {text-align: right;}",
  381. ".tournament-table_td .i-xvm-lang {margin-left: 10px; vertical-align: middle;}",
  382. ".tournament-table_td .b-player-stat {font-size: 18px; }",
  383. // hide elements
  384. "#team_management > div:last-of-type {display: none;}"
  385. ];
  386. style.textContent = styleText.join("");
  387. d.head.appendChild(style);
  388. // end style
  389.  
  390. // add animated loading icon for progress indication
  391. var pageWrpr = d.getElementsByClassName('page-wrapper')[0],
  392. loadGif = sf.elem("div", "processing", "<div class='processing_loader'><img src='https://eu.wargaming.net/clans/static/2.2.8/images/processing/loader.gif' alt='Processing...'></div>");
  393. pageWrpr.appendChild(loadGif);
  394.  
  395. // fetch wnefficiency values - check if array exists in localStorage, otherwise fetch and reload page
  396. var wn = {
  397. stat: sf.storage("wnExpValues", "", "get", "parse"),
  398. date: sf.storage("wnExpDate", "", "get", "parse")+12096e5 >= sc.date, // true if timestamp is less than 2 weeks old, refresh list if false.
  399. vers: [sf.storage("wnExpVers", "", "get")]
  400. };
  401. if (wn.vers[0]==sc.vers && wn.stat && wn.date) {
  402. wn.vers.push(wn.stat.header.version);
  403. wn.stat = wn.stat.data;
  404. }
  405. else {
  406. sf.request("wnData", sc.wn, sf.wn);
  407. }
  408.  
  409. // localization
  410. var loc = [
  411. // thousands separator
  412. {en: ",", ru: " ", cs: " ", de: ".", fr: " ", pl: " ", es:".", tr: "."},
  413. {en: "Script Menu", ru: "Меню скрипта", cs: "Nastavení scriptu", de: "Script-Menü", fr: "Menu du script", pl: "Script Menu", es:"Script Menu", tr: "Script Menu"},
  414. {en: "Refresh WN8 Table", ru: "Обновить таблицу WN8", cs: "Obnov WN8 Tabulku", de: "WN8-Tabelle neu laden", fr: "Rafraîchir la table WN8", pl: "Refresh WN8 Table", es: "Refresh WN8 Table", tr: "Refresh WN8 Table"},
  415. {en: "Script Author:", ru: "Автор скрипта:", cs: "Autor skriptu:", de: "Script-Autor:", fr: "Auteur du script :", pl: "Script Author:", es:"Script Author:", tr: "Script Author:"},
  416. {en: "Contributors", ru: "Contributors", cs: "Kontributoři", de: "Contributors", fr: "Contributeurs", pl: "Contributors", es:"Contributors", tr: "Contributors"},
  417. {en: "Battles", ru: "Бои", cs: "Bitvy", de: "Gefechte", fr: "Batailles", pl: "Bitwy", es: "Batallas", tr: "Savaşlar"},
  418. ];
  419. // process localization
  420. if (sc.locSup.indexOf(sc.loc) == -1) {
  421. sc.loc = "en";
  422. }
  423. for (var _l=0, l_len = loc.length; _l<l_len; _l++) {
  424. loc[_l] = loc[_l][sc.loc];
  425. }
  426.  
  427. // add script info if user menu exists, else wait
  428. var userSet_div = sf.elem("div", "menu-settings menu-top_item", "<a class='cm-user-menu-link' href='#' onClick='return false;'><span class='cm-user-menu-link_cutted-text'>"+loc[1]+"</span><span class='cm-arrow'></span></span>"),
  429. userSet_list = sf.elem("ul", "cm-user-menu"),
  430. userSet_list_items = [
  431. sf.settings("wnRefresh", loc[2]+" [v"+wn.vers[1]+"]"),
  432. sf.elem("li", "b-settingItem settingCredits settingSeperator", "<p>Version: "+sc.vers+"</p>"),
  433. sf.elem("li", "b-settingItem settingCredits", "<p>"+loc[3]+" <a class='b-orange-arrow' href='"+sc.user.wot+"'>Orrie</a></p>"+((sc.cred[sc.loc]) ? "<p>"+loc[4]+" ("+sc.loc.toUpperCase()+"):</p><table>"+sc.cred[sc.loc]+"</table>" : "")),
  434. sf.elem("li", "b-settingItem settingCredits settingLinks", "<p><a class='b-orange-arrow' href='"+sc.host+"'>Greasy Fork</a><a class='b-orange-arrow' href='"+((wg.srv == "na") ? sc.top.na : sc.top.eu)+"'>Support Thread</a></p>")
  435. ],
  436. navMenu = d.getElementById('common_menu'),
  437. navUser = navMenu.getElementsByClassName('cm-menu__user')[0],
  438. navLook = new MutationObserver(function() {
  439. navUser = navMenu.getElementsByClassName('cm-menu__user')[0];
  440. navUser.appendChild(userSet_div);
  441. navLook.disconnect();
  442. });
  443. sf.links(userSet_list, userSet_list_items, "list");
  444. userSet_div.firstElementChild.addEventListener('click', function() {this.classList.toggle('cm-user-menu-link__opened'); this.nextSibling.classList.toggle('cm-user-menu__opened');}, false);
  445. userSet_div.appendChild(userSet_list);
  446. if (navUser) {
  447. navUser.appendChild(userSet_div);
  448. }
  449. navLook.observe(navMenu, {childList: true});
  450.  
  451. // create global post variable
  452. var teamObj = {
  453. cls: d.getElementsByClassName("tournament-table_team"),
  454. ids: []
  455. },
  456. s = {clan:{},user:{}};
  457.  
  458. // fetch userids and store all posts into one obj for later use
  459. var teamTable = d.getElementsByClassName("tournament-table")[0].firstElementChild,
  460. teamCheck = d.getElementsByClassName("tournament-table_team")[0],
  461. teamLook = new MutationObserver(function(m) {
  462. teamCheck = d.getElementsByClassName("tournament-table_team")[0];
  463. if (teamCheck && teamCheck.getAttribute('href') !== "#") {
  464. sf.tableFetch();
  465. teamLook.disconnect();
  466. }
  467. });
  468. if (teamCheck && teamCheck.getAttribute('href') !== "#") {
  469. sf.tableFetch();
  470. }
  471. else {
  472. teamLook.observe(teamTable, {childList: true});
  473. }
  474. }(window));