WoTStatScript - Clanpage

More info for World of Tanks clan page.

当前为 2016-07-03 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name WoTStatScript - Clanpage
  3. // @version 0.9.15.1.7
  4. // @description More info for World of Tanks clan page.
  5. // @author Orrie
  6. // @namespace http://forum.worldoftanks.eu/index.php?/topic/263423-
  7. // @icon http://dl.dropboxusercontent.com/u/12497046/wot/projects/statscript/img/icon.png
  8. // @include http://*.wargaming.net/clans/*/*
  9. // @grant GM_xmlhttpRequest
  10. // @connect www.wnefficiency.net
  11. // @connect api.worldoftanks.eu
  12. // @connect api.worldoftanks.ru
  13. // @connect api.worldoftanks.com
  14. // @connect api.worldoftanks.asia
  15. // @connect api.worldoftanks.kr
  16. // @connect eu.wargaming.net
  17. // @require https://gf.qytechs.cn/scripts/18946-tablesort/code/Tablesort.js?version=120660
  18. // @license MIT License
  19. // ==/UserScript==
  20. (function() {
  21. // global vars
  22. var d = document, c = d.cookie;
  23.  
  24. // get server info and webpage
  25. var wg = {host:d.location.host, href:d.location.href, clan:{}};
  26. wg.srv = wg.host.match(/(eu|ru|na|asia|kr)/)[0];
  27. wg.m = (/players/i.test(wg.href) || /players\/wot/i.test(wg.href)) && !/wowp/i.test(wg.href);
  28. wg.g = /globalmap/i.test(wg.href);
  29.  
  30. // getting claninfo
  31. var emblemName = d.getElementsByClassName('page-header_emblem')[0],
  32. clanName = d.getElementsByClassName('clan_name')[0],
  33. sidebarName = d.getElementsByClassName('sidebar-clan_emblem')[0];
  34. wg.clan.id = wg.href.match(/\/(\d+)/)[1];
  35. wg.clan.name = (emblemName || clanName) ? ((clanName) ? clanName.firstElementChild.innerHTML.replace(/[\[\]]/g,"") : emblemName.alt) : sidebarName.alt;
  36. wg.p = new RegExp("\\["+wg.clan.name+"\\] \\|").test(d.title) && !/wowp/i.test(wg.href);
  37.  
  38. // script variables
  39. var sc = {
  40. vers: ((GM_info) ? GM_info.script.version : ""),
  41. host: "http://gf.qytechs.cn/en/scripts/12137-wotstatscript-clans",
  42. user: {
  43. wl: "http://forum.wotlabs.net/index.php?/user/1618-orrie/",
  44. wot: "http://worldoftanks.eu/community/accounts/505838943-Orrie/"
  45. },
  46. top: {
  47. eu: "http://forum.worldoftanks.eu/index.php?showtopic=263423",
  48. na: "http://forum.worldoftanks.com/index.php?showtopic=404652"
  49. },
  50. cred: { // translators
  51. cs: "<tr><td><a class='b-orange-arrow' href='http://worldoftanks.eu/community/accounts/500744969/'>Crabtr33</a></td><td><a class='b-orange-arrow' href='http://worldoftanks.eu/community/accounts/508323506/'>Ragnarocek</a></td></tr><tr><td><a class='b-orange-arrow' href='http://worldoftanks.eu/community/accounts/508904714/'>jViks</a></td></tr>" ,
  52. de: "<tr><td><a class='b-orange-arrow' href='http://worldoftanks.eu/community/accounts/504873051/'>ArtiOpa</a></td><td><a class='b-orange-arrow' href='http://worldoftanks.eu/community/accounts/501118529/'>Crakker</a></td></tr><tr><td><a class='b-orange-arrow' href='http://worldoftanks.eu/community/accounts/501072645/'>multimill</a></td><td><a class='b-orange-arrow' href='http://worldoftanks.eu/community/accounts/500373105/'>coolathlon</a></td></tr>",
  53. fr: "<tr><td><a class='b-orange-arrow' href='http://worldoftanks.eu/community/accounts/506641783/'>SuperPommeDeTerre</a></td></tr>",
  54. pl: "<tr><td><a class='b-orange-arrow' href='http://worldoftanks.eu/community/accounts/501801562/'>KeluMocy</a></td><td><a class='b-orange-arrow' href='http://worldoftanks.eu/community/accounts/504412736/'>pokapokami</a></td></tr>",
  55. es: "<tr><td><a class='b-orange-arrow' href='http://worldoftanks.eu/community/accounts/512759883/'>Frodo45127</a></td></tr>",
  56. tr: "<tr><td><a class='b-orange-arrow' href='http://worldoftanks.eu/community/accounts/500400806/'>Ufuko</a></td></tr>",
  57. ru: "<tr><td><a class='b-orange-arrow' href='http://worldoftanks.ru/community/accounts/291063/'>Bananium</a></td><td>dimon222</td></tr>"
  58. },
  59. api: {
  60. ru: "98ca7c4fb108175b67d6505b9c3f3ebd",
  61. eu: "a7595640a90bf2d19065f3f2683b171c",
  62. na: "bf5dba0efd444d75147b6222dd903fd2",
  63. asia: "95f8713eccd322e52dbf521dbd28b19c",
  64. kr: "ffea0f1c3c5f770db09357d94fe6abfb"
  65. },
  66. srv: {
  67. wl: false, // wotlabs
  68. nm: false, // noobmeter
  69. vb: false, // vbaddict
  70. ws: false, // wotstats
  71. cs: false, // wotcs
  72. wlf: false, // wot-life
  73. ct: false, // clan tools
  74. kttc: false, // kttc
  75. wots: false, // wots
  76. ch: false, // clan history
  77. wr: false, // wotreplays
  78. we: false // wot event stats
  79. },
  80. wn: "http://www.wnefficiency.net/exp/expected_tank_values_latest.json",
  81. loc: c.match(/wgccfe_language=(\w+)/)[1],
  82. locSup: ["en", "ru", "cs", "de", "fr", "pl", "es", "tr"],
  83. date: Date.now(),
  84. dateFormat: {ru: "ru-RU", eu: "en-GB", na: "en-US", asia: "en-AU", kr: "ko-KR"},
  85. web: {
  86. gecko: typeof InstallTrigger !== 'undefined',
  87. opera: !!window.opera || /opera|opr/i.test(navigator.userAgent),
  88. chrome: !!window.chrome && !!window.chrome.webstore,
  89. safari: /constructor/i.test(window.HTMLElement)
  90. }
  91. };
  92.  
  93. // script functions
  94. var sf = {
  95. tableFetch: function () {
  96. // show animated loading gear
  97. loadGif.classList.remove("js-hidden");
  98. // find required info from table player rows
  99. for (var _rt=0, _rt_len = memObj.cls.rows.length; _rt<_rt_len; _rt++) {
  100. var row = memObj.cls.rows[_rt];
  101. if (!row.classList.contains("tbl-rating_tr__card")) {
  102. var id = row.getAttribute('data-account_id'),
  103. name = row.getElementsByClassName('player_name')[0].innerHTML.match(/[\w\_]+/)[0],
  104. role = row.getElementsByClassName('tbl-rating_td__rank')[0].firstElementChild.classList.item(4).match(/i__(\w+)/)[1];
  105. if (!isNaN(id)) {
  106. memObj.ids.push(id);
  107. s.user[id] = {u:{name:name,id:id,role:role}, v:{frag:0,dmg:0,spot:0,def:0,win:0}, wn8:""};
  108. }
  109. }
  110. }
  111. s.clan = {name:wg.clan.name, wn8:0, win:0, mem: _rt_len};
  112. // request and retrieve statistics from API
  113. if (s.clan.mem > 0) {
  114. sf.request(sc.api.i+memObj.ids.join(','), sf.apiInfoHnd);
  115. }
  116. },
  117. apiInfoHnd: function (resp) { // processing information from player API
  118. var data = JSON.parse(resp).data;
  119. for (var a in data) {
  120. if (data.hasOwnProperty(a)) {
  121. var pData = data[a];
  122. if (pData !== null) {
  123. // store stats
  124. var pDataStats = pData.statistics.all;
  125. s.user[pData.account_id].u = {
  126. name: pData.nickname,
  127. id: pData.account_id,
  128. role: s.user[pData.account_id].u.role,
  129. cid: pData.clan_id,
  130. bat: pDataStats.battles,
  131. win: (pDataStats.wins/pDataStats.battles)*100,
  132. dmg: pDataStats.damage_dealt/pDataStats.battles,
  133. frag: pDataStats.frags/pDataStats.battles,
  134. spot: pDataStats.spotted/pDataStats.battles,
  135. def: pDataStats.dropped_capture_points/pDataStats.battles,
  136. wgr: pData.global_rating,
  137. lng: pData.client_language
  138. };
  139. s.clan.win += (!isNaN(s.user[pData.account_id].u.win)) ? s.user[pData.account_id].u.win : 0;
  140. }
  141. }
  142. }
  143. d.getElementById('js-wn8-status').textContent = "50%";
  144. sf.request(sc.api.v+memObj.ids.join(','), sf.apiVehHnd);
  145. },
  146. apiVehHnd: function (resp) { // processing information from vehicle API and calculate WN8
  147. var data = JSON.parse(resp).data;
  148. for (var p in data) {
  149. if (data.hasOwnProperty(p)) {
  150. var vData = data[p];
  151. if (vData !== null) {
  152. var rWin, rDmg, rFrag, rSpot, rDef, wn8 = 0, battles = 0;
  153. if (s.user[p].u.bat > 0) {
  154. for (var v in vData) {
  155. if (vData.hasOwnProperty(v)) {
  156. // go through each vehicle to get expected stats
  157. for (var _so=0, _so_len = statArr.length; _so<_so_len; _so++) {
  158. if (statArr[_so].IDNum == vData[v].tank_id) {
  159. var vehStat = statArr[_so],
  160. dataBattles = vData[v].statistics.battles;
  161. s.user[p].v.frag += vehStat.expFrag * dataBattles;
  162. s.user[p].v.dmg += vehStat.expDamage * dataBattles;
  163. s.user[p].v.spot += vehStat.expSpot * dataBattles;
  164. s.user[p].v.def += vehStat.expDef * dataBattles;
  165. s.user[p].v.win += vehStat.expWinRate * dataBattles;
  166. battles += dataBattles;
  167. break;
  168. }
  169. }
  170. }
  171. }
  172. // start calculating wn8
  173. rWin = Math.max(((s.user[p].u.win /(s.user[p].v.win /battles)-0.71)/(1-0.71)),0);
  174. rDmg = Math.max(((s.user[p].u.dmg /(s.user[p].v.dmg /battles)-0.22)/(1-0.22)),0);
  175. 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);
  176. 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);
  177. 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);
  178. wn8 = 980*rDmg + 210*rDmg*rFrag + 155*rFrag*rSpot + 75*rDef*rFrag + 145*Math.min(1.8,rWin);
  179. }
  180. // store wn8 and add to clan total
  181. s.user[p].wn8 = wn8;
  182. s.clan.wn8 += wn8;
  183. }
  184. }
  185. }
  186. // calculate average wn8 / winrate and store everything in localStorage, then reload page
  187. s.clan.wn8 = s.clan.wn8/s.clan.mem;
  188. s.clan.win = s.clan.win/s.clan.mem;
  189. sf.storage("statScriptValues_"+wg.clan.id, s, "set", "string");
  190. sf.storage("statScriptDate_"+wg.clan.id, sc.date, "set");
  191. d.getElementById('js-wn8-status').textContent = "100%";
  192. location.reload();
  193. },
  194. apiBanHnd: function (resp) { // processing information from banned API
  195. var data;
  196. if (!memObj.bans.api) {
  197. data = JSON.parse(resp).data;
  198. memObj.bans.api = data;
  199. memObj.bans.f = true;
  200. }
  201. else {
  202. data = memObj.bans.api;
  203. }
  204. for (var a in data) {
  205. if (data.hasOwnProperty(a)) {
  206. var bData = data[a];
  207. var memClass = "js-tooltip-id_js-playerslist-account-name-tooltip-"+a,
  208. memCell = d.getElementsByClassName(memClass)[0].parentNode;
  209. if (bData.ban_time !== null) {
  210. var banTime = (bData.ban_time > 0) ? new Date(bData.ban_time*1000).toLocaleString(sc.dateFormat[wg.srv]) : loc[18];
  211. memCell.appendChild(sf.elem("p", "player_time", banTime));
  212. }
  213. else {
  214. memCell.appendChild(sf.elem("p", "player_time", loc[19]));
  215. }
  216. }
  217. }
  218. },
  219. format: function (input, type) { // input and output formatting
  220. var inputStr = input.toString();
  221. switch(type) {
  222. case (1): // input string into number
  223. return parseFloat(inputStr.replace(/[^\d]/g,""));
  224. case (2): // output number with locale symbol
  225. return inputStr.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1"+loc[0]);
  226. case (3): // input string into number - exclude dots
  227. return parseFloat(inputStr.replace(/[^\d\.]/g,""));
  228. default:
  229. console.error("Error filtering: ", input);
  230. return input;
  231. }
  232. },
  233. color: function (input, type, dec, sym) { // color formatting
  234. var color = colArr.dft[0],
  235. output = input.toFixed(dec);
  236. if (input >= 1000) {
  237. output = sf.format(input.toFixed(dec),2);
  238. }
  239. for (var c in colArr) {
  240. if (colArr.hasOwnProperty(c)) {
  241. if (input >= colArr[c][colArr.id[type]]) {
  242. color = colArr[c][0]; break;
  243. }
  244. }
  245. }
  246. if (loc[0] !== "," && dec !== 0) {
  247. output = output.replace(/\.(\d+)*$/g,",$1");
  248. }
  249. if (sym) {
  250. output += sym;
  251. }
  252. return "<font color='"+color+"'>"+output+"</font>";
  253. },
  254. elem: function (tag, name, html, type, src) { // element creation
  255. var element = d.createElement(tag);
  256. if (name) {
  257. element.className = name;
  258. }
  259. if (html) {
  260. if (/</.test(html)) {
  261. element.innerHTML = html;
  262. }
  263. else {
  264. element.textContent = html;
  265. }
  266. }
  267. if (type) {
  268. element.type = type;
  269. }
  270. if (src) {element.src = src;}
  271. return element;
  272. },
  273. settings: function (name, text, state, dftState, wlist) { // script menu handler
  274. var listItem = sf.elem("li", "b-settingItem "+name, ""),
  275. listItems = d.createDocumentFragment();
  276. if (name == "wnRefresh") {
  277. var refreshBtn = sf.elem("div", "b-settingParent", "<a>"+text+"</a>");
  278. listItem.classList.add("settingSeperator");
  279. refreshBtn.addEventListener('click', function() {localStorage.removeItem("wnExpValues"); location.reload();}, false);
  280. listItems.appendChild(refreshBtn);
  281. }
  282. else if (name == "cleanStorage") {
  283. var cleanBtn = sf.elem("div", "b-settingParent", "<a>"+text+"</a>");
  284. cleanBtn.addEventListener('click', function() {localStorage.clear(); location.reload();}, false);
  285. listItems.appendChild(cleanBtn);
  286. }
  287. else {
  288. var optCheckDiv = sf.elem("div", "b-checkbox", "<span class='b-checkbox_checker'></span>"),
  289. optLabel = sf.elem("label", "b-combobox-label", text),
  290. optCheck = sf.elem("input", "l-box", "", "checkbox");
  291. optLabel.htmlFor = name;
  292. optCheck.name = name;
  293. optCheck.id = name;
  294. if (state) {
  295. optCheckDiv.classList.add("b-checkbox__checked");
  296. optLabel.classList.add("b-combobox-label__checked");
  297. }
  298. optCheck.checked = (state !== undefined) ? state : dftState;
  299. optCheck.addEventListener('click', function() {
  300. sf.storage('statScript_' + this.name, this.checked, "set");
  301. d[this.name] = this.checked;
  302. this.parentNode.classList.toggle('b-checkbox__checked');
  303. this.parentNode.parentNode.classList.toggle('b-combobox-label__checked');
  304. return this.checked;
  305. }, false);
  306. d[optCheck.name] = optCheck.checked;
  307. optCheckDiv.insertBefore(optCheck, optCheckDiv.firstChild);
  308. optLabel.appendChild(optCheckDiv);
  309. listItems.appendChild(optLabel);
  310. if (name == "whitelist") {
  311. var optText = sf.elem("textarea", "l-textarea", "");
  312. optText.placeholder = "Add clanID seperated by comma without spaces: 500004502,500010805";
  313. if (wlist) {
  314. optText.value = wlist;
  315. }
  316. optText.addEventListener('input', function() {
  317. sf.storage('statScript_whitelist_list', optText.value.split(","), "set");
  318. }, false);
  319. listItems.appendChild(optText);
  320. }
  321. }
  322. listItem.appendChild(listItems);
  323. return listItem;
  324. },
  325. links: function (parent, links) { // links handler
  326. var uRows = d.createDocumentFragment();
  327. for (var _l=0, _l_len = links.length; _l<_l_len; ++_l) {
  328. if (links[_l] instanceof HTMLElement) {
  329. uRows.appendChild(links[_l]);
  330. }
  331. else {
  332. uRows.appendChild((links[_l][0] && links[_l][1]) ? sf.elem("li", "", links[_l][1]) : sf.elem("li", "statname", links[_l][0]));
  333. }
  334. }
  335. parent.appendChild(uRows);
  336. },
  337. storage: function (name, data, type, mode) { // localStorage handler
  338. var storage;
  339. switch(type) {
  340. case ("set"):
  341. if (mode == "string") {
  342. data = JSON.stringify(data);
  343. }
  344. storage = localStorage.setItem(name, data);
  345. break;
  346. case ("get"):
  347. storage = localStorage.getItem(name);
  348. if (mode == "parse") {
  349. storage = JSON.parse(storage);
  350. }
  351. break;
  352. default: break;
  353. }
  354. return storage;
  355. },
  356. wn: function (resp) { // wnefficiency handler
  357. sf.storage("wnExpValues", resp, "set");
  358. sf.storage("wnExpDate", sc.date, "set");
  359. sf.storage("wnExpVers", [sc.vers, JSON.parse(resp).header.version], "set", "string");
  360. location.reload();
  361. },
  362. request: function (url, handler) { // request handler
  363. GM_xmlhttpRequest({
  364. method: "GET",
  365. url: url,
  366. headers: {
  367. "Accept": "application/json"
  368. },
  369. onload: function(resp) {
  370. if (resp.status == 200) {
  371. handler(resp.responseText);
  372. }
  373. else {
  374. console.error("Error accessing", url, resp.readyState, resp.status, resp.statusText);
  375. }
  376. },
  377. onerror: function(resp) {
  378. console.error("Error accessing", url, resp.readyState, resp.status, resp.statusText);
  379. }
  380. });
  381. }
  382. };
  383.  
  384. // api links without account id
  385. sc.api.i = "http://api.worldoftanks."+((wg.srv == "na") ? "com" : wg.srv)+"/wot/account/info/?application_id="+sc.api[wg.srv]+"&account_id=";
  386. sc.api.v = "http://api.worldoftanks."+((wg.srv == "na") ? "com" : wg.srv)+"/wot/account/tanks/?application_id="+sc.api[wg.srv]+"&account_id=";
  387.  
  388. // fetch wnefficiency values - check if array exists in localStorage, otherwise fetch and reload page
  389. var wn = {
  390. values: sf.storage("wnExpValues", "", "get", "parse"),
  391. date: sf.storage("wnExpDate", "", "get", "parse")+12096e5 >= sc.date, // true if timestamp is less than 2 weeks old, refresh list if false.
  392. vers: sf.storage("wnExpVers", "", "get", "parse") || ""
  393. }, statArr = [];
  394. if (wn.vers[0]==sc.vers && wn.values && wn.date) {
  395. statArr = wn.values.data;
  396. }
  397. else {
  398. sf.request(sc.wn, sf.wn);
  399. }
  400.  
  401. // fetch stored clanlist stats - check if array exists in localStorage, otherwise tag fetching to true
  402. var ss = {
  403. val: sf.storage("statScriptValues_"+wg.clan.id, "", "get", "parse"),
  404. date: sf.storage("statScriptDate_"+wg.clan.id, "", "get", "parse")+6048e5 >= sc.date // true if timestamp is less than 1 weeks old, refresh list if false.
  405. }, s = {clan:{},user:{}}, statFetch = false;
  406. if (ss.val && ss.date) {
  407. s = ss.val;
  408. }
  409. else {
  410. statFetch = true;
  411. }
  412.  
  413. // inserting style into head
  414. var style = sf.elem("style", "wotstatscript", "", "text/css");
  415. d.head.appendChild(style);
  416.  
  417. // colour scale array
  418. var colArr = {
  419. // col wr bat sr hr dmg wgr wn8 wn7 eff nm
  420. sUni: [ "#5A3175", 65, 30000, 50, 80, 300, 9900, 2900, 2050, 2050, 2000 ], // 99.99% super unicum
  421. uni: [ "#83579D", 60, 25000, 46, 75, 270, 9000, 2450, 1850, 1800, 1950 ], // 99.90% unicum
  422. gr8: [ "#3972C6", 56, 21000, 42, 70, 240, 8500, 2000, 1550, 1500, 1750 ], // 99.00% great
  423. vGud: [ "#4099BF", 54, 17000, 38, 65, 210, 6500, 1600, 1350 ], // 95.00% very good
  424. good: [ "#4D7326", 52, 13000, 34, 60, 180, 5000, 1200, 1100, 1200, 1450 ], // 82.00% good
  425. aAvg: [ "#849B24", 50, 10000, 30, 55, 150, 4000, 900 ], // 63.00% above average
  426. avg: [ "#CCB800", 48, 7000, 25, 50, 120, 3000, 650, 900, 900, 1250 ], // 40.00% average
  427. bAvg: [ "#CC7A00", 47, 3000, 20, 45, 90, 2000, 450, 700, 600, 1150 ], // 20.00% below average
  428. bas: [ "#CD3333", 46, 1000, 15, 40, 60, 1500, 300, 500 ], // 6.00% basic
  429. beg: [ "#930D0D", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], // 0.00% beginner
  430. dft: [ "#6B6B6B" ], // default
  431. id: { "col": 0, "wr": 1, "bat": 2, "sr": 3, "hr": 4, "dmg": 5, "wgr": 6, "wn8": 7, "wn7": 8, "eff": 9, "nm": 10 } // type identifier
  432. };
  433.  
  434. // localization
  435. // cz-czech - Crabtr33 and Ragnarocek
  436. // de-german - ArtiOpa, Crakker and multimill
  437. // fr-french - SuperPommeDeTerre
  438. // pl-polish - KeluMocy and pokapokami
  439. // es-spanish - Frodo45127
  440. // tr-turkish - Ufuko
  441. // ru-russian - dimon222
  442. var loc = [
  443. // thousands separator
  444. { en: ",", ru: " ", cs: " ", de: ".", fr: " ", pl: " ", es:" ", tr: "."},
  445. // clan page
  446. { en: "Clan Stats", ru: "Статистика клана", cs: "Stat. klanu", de: "Clanstatistiken", fr: "Statistiques du clan", pl: "Statystyki klanu", es: "Estadísticas del clan", tr: "Klan İstatistikleri"},
  447. { en: "Replays:", ru: "Реплеи:", cs: "Záznamy:", de: "Replays", fr: "Replays:", pl: "Powtórki:", es: "Repeticiones:", tr: "Replayler"},
  448. // memberlist
  449. { en: "Script Menu", ru: "Меню скрипта", cs: "Nastavení scriptu", de: "Script-Menü", fr: "Menu du script", pl: "Script Menu", es:"Script Menu", tr: "Script Menu"},
  450. { en: "Load Stats Automatically", ru: "Load Stats Automatically", cs: "Nahrát stat. automaticky", de: "Load Stats Automatically", fr: "Charger les statistiques automatiquement", pl: "Load Stats Automatically", es:"Load Stats Automatically", tr: "Load Stats Automatically"},
  451. { en: "Use Whitelist", ru: "Use Whitelist", cs: "Použi whitelist", de: "Use Whitelist", fr: "Utiliser la liste blanche", pl: "Use Whitelist", es:"Use Whitelist", tr: "Use Whitelist"},
  452. { 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"},
  453. { en: "Clean Script Database", ru: "Clean Script Database", cs: "Vyčisti db scriptu", de: "Clean Script Database", fr: "Nettoyer la base de données du script", pl: "Clean Script Database", es: "Clean Script Database", tr: "Clean Script Database"},
  454. { en: "Average Winrate", ru: "Average Winrate", cs: "Průměrný winrate", de: "Average Winrate", fr: "Ratio de victoire moyen", pl: "Average Winrate", es:"Average Winrate", tr: "Average Winrate"},
  455. { en: "Average WN8", ru: "Average WN8", cs: "Průměrné WN8", de: "Average WN8", fr: "Average WN8", pl: "WN8 moyen", es:"Average WN8", tr: "Average WN8"},
  456. { en: "Overall Average Winrate", ru: "Overall Average Winrate", cs: "Průměrný winrate", de: "Overall Average Winrate", fr: "Overall Average Winrate", pl: "Overall Average Winrate", es:"Overall Average Winrate", tr: "Overall Average Winrate"},
  457. { en: "Overall Average WN8", ru: "Overall Average WN8", cs: "Overall Average WN8", de: "Overall Average WN8", fr: "Overall Average WN8", pl: "Overall Average WN8", es:"Overall Average WN8", tr: "Overall Average WN8"},
  458. { en: "Fetch WN8 for Clan", ru: "Fetch WN8 for Clan", cs: "Obnov WN8 pre klan", de: "Fetch WN8 for Clan", fr: "Calculer le WN8 pour le clan", pl: "Fetch WN8 for Clan", es:"Fetch WN8 for Clan", tr: "Fetch WN8 for Clan"},
  459. { en: "Fetching WN8 for Clan!", ru: "Fetching WN8 for Clan!", cs: "Obnovuju WN8 pro klan!", de: "Fetching WN8 for Clan!", fr: "Walcul du WN8 pour le clan !", pl: "Fetching WN8 for Clan!", es:"Fetching WN8 for Clan!", tr: "Fetching WN8 for Clan!"},
  460. { en: "WN8 Fetched for Clan!", ru: "WN8 Fetched for Clan!", cs: "WN8 obnoveno pro klan!", de: "WN8 Fetched for Clan!", fr: "WN8 calculé pour le clan !", pl: "WN8 Fetched for Clan!", es:"WN8 Fetched for Clan!", tr: "WN8 Fetched for Clan!"},
  461. { en: "Not Found", ru: "Not Found", cs: "Nenalezeno", de: "Not Found", fr: "Non trouvé", pl: "Not Found", es:"Not Found", tr: "Not Found"},
  462. { en: "New Members:", ru: "New Members:", cs: "Noví členové:", de: "New Members:", fr: "Nouveaux membres :", pl: "New Members:", es:"New Members:", tr: "New Members:"},
  463. { en: "Banned Members:", ru: "Banned Members:", cs: "Noví členové:", de: "Banned Members:", fr: "Membres bannis:", pl: "Banned Members:", es:"Banned Members:", tr: "Banned Members:"},
  464. { en: "Currently Unavailable", ru: "Currently Unavailable", cs: "Currently Unavailable", de: "Currently Unavailable", fr: "Indisponible actuellement", pl: "Currently Unavailable", es:"Currently Unavailable", tr: "Currently Unavailable"},
  465. { en: "Ban ended, but no login", ru: "Ban ended, but no login", cs: "Ban ended, but no login", de: "Ban ended, but no login", fr: "Ban terminé, mais aucune connexion", pl: "Ban ended, but no login", es:"Ban ended, but no login", tr: "Ban ended, but no login"},
  466. { en: "Script Author:", ru: "Автор скрипта:", cs: "Autor skriptu:", de: "Script-Autor:", fr: "Auteur du script:", pl: "Script Author:", es:"Script Author:", tr: "Script Author:"},
  467. { en: "Contributors", ru: "Contributors", cs: "Kontributoři", de: "Contributors", fr: "Contributeurs", pl: "Contributors", es:"Contributors", tr: "Contributors"},
  468. { en: "Battle Schedule", ru: "Battle Schedule", cs: "Battle Schedule", de: "Battle Schedule", fr: "Battle Schedule", pl: "Battle Schedule", es:"Battle Schedule", tr: "Battle Schedule"},
  469. { en: "Clan Wars Countdown:", ru: "Clan Wars Countdown:", cs: "Clan Wars Countdown:", de: "Clan Wars Countdown:", fr: "Clan Wars Countdown:", pl: "Clan Wars Countdown:", es:"Clan Wars Countdown:", tr: "Clan Wars Countdown:"},
  470. { en: "Battle Count:", ru: "Battle Count:", cs: "Battle Count:", de: "Battle Count:", fr: "Battle Count:", pl: "Battle Count:", es:"Battle Count:", tr: "Battle Count:"},
  471. { en: "Gold Income:", ru: "Gold Income:", cs: "Gold Income:", de: "Gold Income:", fr: "Gold Income:", pl: "Gold Income:", es:"Gold Income:", tr: "Gold Income:"},
  472. { en: "Province", ru: "Провинция", cs: "Province", de: "Province", fr: "Province", pl: "Province", es:"Province", tr: "Province"},
  473. { en: "Map", ru: "Игровая карта", cs: "Map", de: "Map", fr: "Map", pl: "Map", es:"Map", tr: "Map"},
  474. { en: "Timezone", ru: "Timezone", cs: "Timezone", de: "Timezone", fr: "Timezone", pl: "Timezone", es:"Timezone", tr: "Timezone"},
  475. { en: "Fame", ru: "Fame", cs: "Fame", de: "Fame", fr: "Fame", pl: "Fame", es:"Fame", tr: "Fame"},
  476. { en: "Gold", ru: "Gold", cs: "Gold", de: "Gold", fr: "Gold", pl: "Gold", es:"Gold", tr: "Gold"},
  477. { en: "Owner", ru: "Owner", cs: "Owner", de: "Owner", fr: "Owner", pl: "Owner", es:"Owner", tr: "Owner"},
  478. { en: "ELO", ru: "ELO", cs: "ELO", de: "ELO", fr: "ELO", pl: "ELO", es:"ELO", tr: "ELO"},
  479. { en: "Type", ru: "Type", cs: "Type", de: "Type", fr: "Type", pl: "Type", es:"Type", tr: "Type"},
  480. { en: "Status", ru: "Status", cs: "Status", de: "Status", fr: "Status", pl: "Status", es:"Status", tr: "Status"},
  481. { en: "Attackers", ru: "Attackers", cs: "Attackers", de: "Attackers", fr: "Attackers", pl: "Attackers", es:"Attackers", tr: "Attackers"},
  482. { en: "Turns", ru: "Turns", cs: "Turns", de: "Turns", fr: "Turns", pl: "Turns", es:"Turns", tr: "Turns"},
  483. { en: "Last Updated:", ru: "Last Updated:", cs: "Last Updated:", de: "Last Updated:", fr: "Last Updated:", pl: "Last Updated:", es:"Last Updated:", tr: "Last Updated:"},
  484. { en: "Updating...", ru: "Updating...", cs: "Updating...", de: "Updating...", fr: "Updating...", pl: "Updating...", es:"Updating...", tr: "Updating..."},
  485. { en: "See you next time.", ru: "See you next time.", cs: "See you next time.", de: "See you next time.", fr: "See you next time.", pl: "See you next time.", es:"See you next time.", tr: "See you next time."},
  486. { en: "Not Started", ru: "Not Started", cs: "Not Started", de: "Not Started", fr: "Not Started", pl: "Not Started", es:"Not Started", tr: "Not Started"},
  487. { en: "Ongoing", ru: "Ongoing", cs: "Ongoing", de: "Ongoing", fr: "Ongoing", pl: "Ongoing", es:"Ongoing", tr: "Ongoing"},
  488. { en: "Planned", ru: "Planned", cs: "Planned", de: "Planned", fr: "Planned", pl: "Planned", es:"Planned", tr: "Planned"},
  489. { en: "Defense", ru: "Defense", cs: "Defense", de: "Defense", fr: "Defense", pl: "Defense", es:"Defense", tr: "Defense"},
  490. { en: "Owner", ru: "Owner", cs: "Owner", de: "Owner", fr: "Owner", pl: "Owner", es:"Owner", tr: "Owner"},
  491. { en: "Attack", ru: "Attack", cs: "Attack", de: "Attack", fr: "Attack", pl: "Attack", es:"Attack", tr: "Attack"},
  492. { en: "Free Round", ru: "Free Round", cs: "Free Round", de: "Free Round", fr: "Free Round", pl: "Free Round", es:"Free Round", tr: "Free Round"},
  493. { en: "No Owner", ru: "No Owner", cs: "No Owner", de: "No Owner", fr: "No Owner", pl: "No Owner", es:"No Owner", tr: "No Owner"},
  494. { en: "No Attacks", ru: "No Attacks", cs: "No Attacks", de: "No Attacks", fr: "No Attacks", pl: "No Attacks", es:"No Attacks", tr: "No Attacks"},
  495. { en: "No Battles", ru: "No Battles", cs: "No Battles", de: "No Battles", fr: "No Battles", pl: "No Battles", es:"No Battles", tr: "No Battles"},
  496. { en: "No Division", ru: "No Division", cs: "No Division", de: "No Division", fr: "No Division", pl: "No Division", es:"No Division", tr: "No Division"},
  497. { en: "Division Data not Available!", ru: "Division Data not Available!", cs: "Division Data not Available!", de: "Division Data not Available!", fr: "Division Data not Available!", pl: "Division Data not Available!", es:"Division Data not Available!", tr: "Division Data not Available!"},
  498. { en: "Clan ID Error", ru: "Clan ID Error", cs: "Clan ID Error", de: "Clan ID Error", fr: "Clan ID Error", pl: "Clan ID Error", es:"Clan ID Error", tr: "Clan ID Error"},
  499. { en: "No Event Campaign", ru: "No Event Campaign", cs: "No Event Campaign", de: "No Event Campaign", fr: "No Event Campaign", pl: "No Event Campaign", es:"No Event Campaign", tr: "No Event Campaign"},
  500. { en: "No Planned Battles", ru: "No Planned Battles", cs: "No Planned Battles", de: "No Planned Battles", fr: "No Planned Battles", pl: "No Planned Battles", es:"No Planned Battles", tr: "No Planned Battles"},
  501. { en: "Hours", ru: "Hours", cs: "Hours", de: "Hours", fr: "Hours", pl: "Hours", es:"Hours", tr: "Hours"},
  502. { en: "Mins", ru: "Mins", cs: "Mins", de: "Mins", fr: "Mins", pl: "Mins", es:"Mins", tr: "Mins"},
  503. { en: "Secs", ru: "Secs", cs: "Secs", de: "Secs", fr: "Secs", pl: "Secs", es:"Secs", tr: "Secs"},
  504. { en: "Event Only Schedule", ru: "Event Only Schedule", cs: "Event Only Schedule", de: "Event Only Schedule", fr: "Event Only Schedule", pl: "Event Only Schedule", es:"Event Only Schedule", tr: "Event Only Schedule"},
  505. { en: "Currently Running", ru: "Currently Running", cs: "Currently Running", de: "Currently Running", fr: "Currently Running", pl: "Currently Running", es:"Currently Running", tr: "Currently Running"},
  506. { en: "Concurrent Battles:", ru: "Concurrent Battles:", cs: "Concurrent Battles:", de: "Concurrent Battles:", fr: "Concurrent Battles:", pl: "Concurrent Battles:", es:"Concurrent Battles:", tr: "Concurrent Battles:"},
  507. { en: "Next Opponent", ru: "Next Opponent", cs: "Next Opponent", de: "Next Opponent", fr: "Next Opponent", pl: "Next Opponent", es:"Next Opponent", tr: "Next Opponent"}
  508. // 61 localized strings
  509. // {en: "", ru: "", cs: "", de: "", fr: "", pl: "", es:"", tr: ""}
  510. ];
  511.  
  512. // region settings for external sites
  513. switch(wg.srv) {
  514. case ("eu"): // eu server
  515. sc.srv.wl = sc.srv.nm = sc.srv.vb = sc.srv.ws = sc.srv.cs = sc.srv.wlf = sc.srv.ct = sc.srv.kttc = sc.srv.ch = sc.srv.wr = sc.srv.we = wg.srv;
  516. break;
  517. case ("ru"): // ru server
  518. sc.srv.wl = sc.srv.nm = sc.srv.vb = sc.srv.ws = sc.srv.cs = sc.srv.ct = sc.srv.kttc = sc.srv.wots = sc.srv.ch = sc.srv.wr = wg.srv;
  519. break;
  520. case ("na"): // na server - american english
  521. sc.srv.wl = sc.srv.nm = sc.srv.vb = sc.srv.ws = sc.srv.cs = sc.srv.wlf = sc.srv.ct = sc.srv.kttc = sc.srv.ch = wg.srv; sc.srv.wr = "com";
  522. break;
  523. case ("asia"): // asia server
  524. sc.srv.wl = sc.srv.nm = sc.srv.vb = sc.srv.ws = sc.srv.cs = "sea"; sc.srv.ct = sc.srv.kttc = sc.srv.ch = wg.srv; sc.srv.wr = "com";
  525. break;
  526. case ("kr"): // korean server
  527. sc.srv.wl = sc.srv.nm = sc.srv.vb = sc.srv.ws = sc.srv.cs = sc.srv.ct = sc.srv.ch = wg.srv; sc.srv.wr = "com";
  528. break;
  529. default: break;
  530. }
  531.  
  532. // set script language to english if an unsupported language is detected
  533. var locMiss = 0;
  534. if (sc.locSup.indexOf(sc.loc) == -1) {
  535. sc.loc = "en";
  536. }
  537.  
  538. // process localization
  539. for (var _l=0, l_len = loc.length; _l<l_len; _l++) {
  540. var langLoc = loc[_l][sc.loc];
  541. if (sc.loc !== "en" && langLoc == loc[_l].en && !loc[_l].i) {
  542. locMiss ++;
  543. console.info("Missing translation at line "+(_l+550)+" - en:\""+loc[_l].en+"\"", sc.loc+":\""+loc[_l][sc.loc]+"\"");
  544. }
  545. loc[_l] = langLoc;
  546. }
  547.  
  548. // add language to body classname for language based styling
  549. d.body.classList.add("lang-"+sc.loc);
  550.  
  551. // variables for dropbox, css and data uri
  552. var css = {
  553. u: {
  554. cIcons: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAACgCAMAAAAy5xwmAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAK7UExURUxpcWV+bG+/jnacsI2z0I+z0JCzzqDAsqXAt6mwjrG/0rPAwr7BzL/D0sDBzdGli9Kyn////3qsYKWJZ1VTZS2Szlm3c1y7cmC5cWRoZWVrZ86LTdGOR9OKSS2RzS2Szi2Tzy+SzVm2c1m3c2C5cWVrZ4J/hc6LTc+NRtCNR9GbbCiU1F29eIGChdCOR9yGOh6R11e8c+KIOB6S2BSR3iGT2Uu+cVi8dPehhVBOlUqkxTyqwTYmS+rBihgYGEeyyUVUtciUVurTn5pNG/R0WTyqwdrhhaTM2Xcnqz+wyPT5+xkXFDFly/+BhRgXFUOxydurZv/0xykpKaBYHb7BzMXDy38axfvxhRsaGvhrBXAxlv+ChTNly77BzL7BzL/BzUCvyMXDy77BzMDF08PC0cXB0sXDy8jEy77BzMPB0M/i4L3D0cHBzrzG177BzL/Czb/CzS4oKP9rAEGvx/+Ghe3nzzCT0zJUoYfG5e7Eih8dHH8axf/nhUGxybzl9jFlyykpKXI1lMuXaWFoIv+Ahdj9hWKn1Nfp9PLs4RsZGv9sAaNdev+phT6txDJlzCopKaDqhf9/hb7BzGJgYWJiYduIPhyR1x+T2iGT2CKT2FS8cFa9dVe9dVi+dGZlZmZmZn8axduKQduKQ9yKQTyqwXAxltU5LiIgH+fIn77BzPVhCvrv1R+T2h+T2yGT2iKS1yKS2CKT2Fa9dVi+dGZkZmZmZtqJQ9qKQ9uJQ9uKQ9yKQdyLQeicAGJUZdfs+f9qACYmJh+T2iKT2Fa9dVi9dFi+dGZkZmZmZtuKQ9yLQb7BzH8axTJn0TyqwSEXFiQjIykoKDAiITgrKUUyMFBBN2tGQnAxlnen13h0a3lMR6LT66WZlbqRrr7BzL7Bzb/CzcDDrcTQ3OPSvuX2/Pb7/P758P9qAP/z2v///9BBknIAAADOdFJOUwAAAAAAAAAAAAAAAAAAAAAAAAEBBQoKCgoKCgoKCgsLCwsLCwsLCwsLCwsMDAwMDA0NDQ4PDw8PEBETFxgiLzE1OTk+QUROT1JVVVZXX2pvcXF2eHh5fX2AgIGBhoiJiYqMjY2NjY2Njo6Oj4+Tk5OUnJ+goaWqqqqqq6yztLS3ub29vsPExsbGysrQ0NHT1tfb4+Tk5OXl5eXl5eXl5eXl5eXl6Ojq6+3w8PH09PT09PT09PT09PT09PT09fb29vf4+Pj4+Pj4+Pj7/f7+oQ6AsQAABQ9JREFUSMe9lYlXG1UUh6/7vlTHfWnVKuK+m04niwKBNBC0qKQh1RG3WrUaAlVj0xgWZRAIdd9X0qlt3XcLJNZdCDNMJhGKUVuSlD/D+95MJkmPPfZ4PN4Db+793u/ed9/M4wHw72wpP5BIWIuxdWA4kXCAxWfEicRwDSyJ+GAJBcFEgl8KzOOyBW4hcQ3GDIkjDIzXIfAnhlHpk+XlUDf+GILhhB9guSzHMWP8TQR0gbgsRwDBOAU1RIAZOiDGReQIV9YrwzHwP5pXG0Mhr9dW7yVGwQQ1b0EVCg1SEAqxmh59CA3avCEU1QPQWW/9BFtPPU0wOFg/GCKKiZCeUjC9rq1g/912PNF0wehr9Rhh2kMFxfmo9p413xAwFHhshiCMIIodhnWBJw3pMKldpy2BD9CUTDRMvijWApqBWnJUMDFNihKffFvaEl2lTjsCUQOkaVY4XQRRXMKm9au3HmZ0QbSwOU+dsUF9+3SMevZ4N2Z72cli7END5lKA8ZAd7EVmMvfYe6Cnp5hm7zHZwdRTlDQ34ySzzm4U1dzmZmPRdVRs7kednczZ19Fypn4z/vabANq1ZKa9ARraW1rA1K2Xb2g3dVebNpiru/UGzN0N7Qy0EJHeYPeG6sKoWUs70TZsMBl7oB5j3vuR4VwBCzBun8X4k5QkJwJJdNF1uYAsBSwcZwlIopPUwhm3KyBGfK6AJFg4YAQp4BRHZ2fVuChLYgAsohSPy9Pq9LQsipLghoCEJivqrEqcAAdu8pSU6VGZAgYsApWoCp3AhRknZgrCaEQQ0CG9cW4s5XK7cGm9M5IUV+K4plu7QxiLG9XYgpMzbhOLS3A7LXu5U3xivMREH4hSicmyCPHSeHQ0UgYi4aeqNCDTjYjOFbE+CmRVJQ939eZ8jIJIV5dTkISqvrwO3Cs2r6jqamrL64BMxfpGRmI6wFro5UdG8hQIkg9rGRaDKh/NLYK+jRtjZSC2uSSBgny+HLTFyqxtn64Ydk+XLwLiWlne+Fdj9bNWYHl2QE9iB6w46eD9jiAlbNDh5x3A843+xiD5Swqiw/NgRYk1yDIMJqAAazT6g44g8H7Ah7+RJDt43sEGgyx5at+a5R28A394q/G5mQGGGWBLu7eSDvf1OuWESTzz2khNmJyclPSR2iQxfaQmUlcsAvQlY/xbmyoaRu4pmFIUZTapaCCAg5JMJrOzKuIpEAlNqqqaRZJUFJoOaiqVyiJJJhVAmQKpmZkZjFNqMglJQmcImE2lVDUJEQ2kUhgjUIHz6YoZQhFgH8o/vJva68rB+rEOzaldRmz1XK73Bg3smEfLzec69WvINkfA/CajwMMaeFQP12bnDdtSheCR+RLrJGuVArLs2pJ40/WkibHdTetzncuym6rmcjeSGnO5jrH53iezWzqyu+kyv84VMnK9TbTxJ3bt/HPnb7t2dKyu3afzseDIot307tMLykBr5pcysCpz+80FsGYNie856EAdtGYyK2/N3H3wZVdqYFXmtpWZ3+84/MLnX6RgVebeo4964L5jD7hq+3YCWjN3Hbr/YcdccMXxV7//EYIH/7jzkMuvOe7S594646z3CHjo/iMuevnVky756eeKRVsJuPi8/a797tvFlV9tq1hEFc8+c8rZn3y8uPKLbRULt36I4Mcfzj0HwfmfE/ABgs8+paDyy68rzqQ1iOJ7rIFFF35D+njj9VNPfO2Vk09/+53TTnjhpQV/AasrpIaeUd4CAAAAAElFTkSuQmCC",
  555. arrow: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAECAMAAAB1GNVPAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAPUExURf///////////0xpcf///17pIXYAAAAEdFJOU393iAAiK7rGAAAAH0lEQVQI1w3GwQEAMBBEQBf6rzn7YeipxA0bXoU4LB8EgABGoTqNxwAAAABJRU5ErkJggg=="
  556. },
  557. i: {
  558. loader: "/clans/static/2.2.8/images/processing/loader.gif",
  559. arrow: "http://static-ptl-eu.gcdn.co/static/wot/common/css/scss/content/links/img/orange_arrow.png"
  560. }
  561. };
  562.  
  563. // style contents
  564. var styleClan = [
  565. // fix width for header with low resolution
  566. ".search-form__place-header {width: 30%;}",
  567. ".search-form__place-header.search-form__state-on {width: 410px;}",
  568. // loading text
  569. ".processing_loader span {display: table; margin: 0 auto;}",
  570. // links menu rules
  571. ".menu-clan_links {padding: 0;}",
  572. ".menu-clan_links.cm-parent-link__opened {border: 1px solid #313335;}",
  573. ".menu-clan_links .menu-top_link {cursor: pointer; padding: 0 8px 0 9px;}",
  574. ".menu-clan_links .menu-top_link.cm-parent-link__opened {background: #0E0E0E; border-left: 1px solid #313335; border-right: 1px solid #313335; margin-left: -1px;}",
  575. ".menu-clan_links .cm-arrow {background-image: url('"+css.u.arrow+"'); display: inline-block; margin-left: 5px; opacity: 0.5; vertical-align: middle; transition: opacity 0.2s ease 0s; height: 4px; width: 7px;}",
  576. ".menu-clan_links .cm-parent-link__opened .cm-arrow {opacity: 1; transform: rotate(180deg);}",
  577. ".menu-clan_links .clan-links {background: rgba(14, 14, 14, 0.99); border: 1px solid #313335; display: none; box-shadow: 0px 0px 25px rgba(0, 0, 0, 0.4); margin-left: -1px; padding: 14px 16px; position: absolute;}",
  578. ".menu-clan_links .cm-sublist__opened {display: block;}",
  579. ".menu-clan_links .clan-links td {padding: 0 10px;}",
  580. ".sl-icon {background: url('"+css.u.cIcons+"') no-repeat; display: inline-block; margin: -2px 8px 0px 0px; vertical-align: middle; height: 16px; width: 16px;}",
  581. ".sl-wl {background-position: 0px 0px;}",
  582. ".sl-nm {background-position: 0px -16px;}",
  583. ".sl-ct {background-position: 0px -32px;}",
  584. ".sl-cs {background-position: 0px -48px;}",
  585. ".sl-kttc {background-position: 0px -64px;}",
  586. ".sl-wlife {background-position: 0px -80px;}",
  587. ".sl-as {background-position: 0px -96px;}",
  588. ".sl-wr {background-position: 0px -112px;}",
  589. ".sl-vb {background-position: 0px -128px;}",
  590. ".sl-we {background-position: 0px -144px;}",
  591. // rating profile rules
  592. ".rating-profile {width: 70%; margin: 0px auto;}",
  593. // settings menu rules
  594. "#common_menu .menu-settings {color: #7C7E80; display: inline-block;}",
  595. "#common_menu .menu-settings .cm-user-menu-link {margin: 0 10px 0 0;}",
  596. "#common_menu .menu-settings .cm-user-menu-link_cutted-text {max-width: unset;}",
  597. "#common_menu .menu-settings .cm-user-menu {min-width: 200px; padding: 15px;}",
  598. "#common_menu .menu-settings .cm-parent-link:hover {cursor: pointer;}",
  599. "#common_menu .menu-settings .b-settingItem {margin: 6px 0px; text-align: center;}",
  600. "#common_menu .menu-settings label {display: table; line-height: normal; cursor: pointer; margin: 0 auto;}",
  601. "#common_menu .menu-settings .l-box {display: none;}",
  602. "#common_menu .menu-settings .b-checkbox {height: 16px; width: 16px; float: left; margin-right: 5px;}",
  603. "#common_menu .menu-settings .b-checkbox span {height: 16px; width: 16px;}",
  604. "#common_menu .menu-settings .b-combobox-label__checked {color: #DCDCDC;}",
  605. "#common_menu .menu-settings .b-settingItem .b-combobox-label:hover {color: #DCDCDC;}",
  606. "#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);}",
  607. "#common_menu .menu-settings .b-settingItem .b-combobox-label:hover .b-checkbox.b-checkbox__checked {background-position: 0px -68px;}",
  608. "#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;}",
  609. "#common_menu .menu-settings textarea::-webkit-input-placeholder {color: #FFFFFF;}",
  610. "#common_menu .menu-settings textarea::-moz-placeholder {color: #FFFFFF;}",
  611. "#common_menu .menu-settings .b-settingParent {line-height: 26px;}",
  612. "#common_menu .menu-settings .b-settingParent a {cursor: pointer; color: #B1B2B3; text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.5);}",
  613. "#common_menu .menu-settings .b-settingParent a:hover {color: #FFFFFF; text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.75); text-decoration: underline;}",
  614. "#common_menu .menu-settings .settingCredits {margin: 2px 0px;}",
  615. "#common_menu .menu-settings .settingCredits h1 {color: #B1B2B3;}",
  616. "#common_menu .menu-settings .settingCredits table {font-size: 12px; margin: 0 auto; width: unset;}",
  617. "#common_menu .menu-settings .settingCredits table td {padding: 0 5px;}",
  618. "#common_menu .menu-settings .settingCredits p {font-size: 12px; padding: 2px 0;}",
  619. "#common_menu .menu-settings .settingCredits .b-orange-arrow {background: url('"+css.i.arrow+"') 100% 0 no-repeat; color: #F25322; line-height: 14px; padding-right: 9px;}",
  620. "#common_menu .menu-settings .settingCredits .b-orange-arrow:hover {color: #FF7432;}",
  621. "#common_menu .menu-settings .settingCredits.settingSeperator {border-top: 1px dashed #212123; margin-top: 6px; padding-top: 12px;}",
  622. "#common_menu .menu-settings .settingCredits.settingSeperator.b-wnRefresh {margin-top: 11px; padding-top: 6px;}",
  623. "#common_menu .menu-settings .settingCredits.settingLinks a {margin: 0 5px;}",
  624. // memberpage rules
  625. ".page-header {padding: 30px 0 30px 75px}",
  626. ".page-header_meminfo {display: table; margin: 0px auto; position: absolute; top: 3px; right: 0px; left: 0px; text-align: center;}",
  627. ".page-header_meminfo span {margin: 0 5px;}",
  628. ".page-header_ban {color: #E5B12E;}",
  629. ".page-header_mem {color: #E5B12E;}",
  630. ".js-page-header-view .page-header_mem {margin-left: 25px;}",
  631. // button fetch rules
  632. ".b-button-stats {border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 2px; position: absolute; right: 0; top: 9px;}",
  633. ".b-button-stats a {background: rgba(255, 255, 255, 0.1); color: #FFFFFF; cursor: pointer; font-size: 17px; line-height: 45px; display: block; padding: 0px 15px; transition: all 0.2s ease 0s;}",
  634. ".b-button-stats a:hover {background: rgba(229, 177, 46, 0.25);}",
  635. // rating players rules
  636. ".rating-players {height: 200px;}",
  637. ".rating-players tbody {width: 95%; display: table; margin: 0px auto;}",
  638. ".rating-players_item__data {padding-top: 25px; width: 14%;}",
  639. ".rating-players_item__average {padding-top: 10px; width: 16%;}",
  640. ".rating-players_stats {font-size: 40px;}",
  641. // membertable rules
  642. ".js-expander-link-view {display: table; position: absolute; top: 333px;}",
  643. "#js-playerslist-table {margin-top: 7px;}",
  644. ".tbl-rating_th__wn a {cursor: pointer;}",
  645. ".player_time {position: absolute; right: 0; top: 18px;}"
  646. ];
  647. style.textContent = styleClan.join("");
  648. // end style
  649.  
  650. // add animated loading icon for progress indication
  651. var layoutHolder = d.getElementsByClassName('layout_holder')[0],
  652. loadGif = sf.elem("div", "processing js-hidden", "<div class='processing_loader'><img src='"+css.i.loader+"' alt='Processing...'><span id='js-wn8-status'></span></div>");
  653. layoutHolder.appendChild(loadGif);
  654.  
  655. // script link and settings
  656. var clanSet_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[3]+"</span><span class='cm-arrow'></span></span>"),
  657. clanSet_list = sf.elem("ul", "cm-user-menu", ""),
  658. clanSet_list_locItem = sf.elem("li", "b-settingItem settingCredits settingSeperator", ""),
  659. enableOnPageload = sf.storage("statScript_onPageload", "", "get", "parse"),
  660. enableWhitelist = sf.storage("statScript_whitelist", "", "get", "parse"),
  661. enableWhiteList_list = sf.storage("statScript_whitelist_list", "", "get"),
  662. enableEventOnly = sf.storage("statScript_eventOnly", "", "get", "parse"),
  663. whiteListArray = (enableWhiteList_list) ? enableWhiteList_list.split(",") : "",
  664. clanSet_list_items = [
  665. sf.settings("onPageload", loc[4], enableOnPageload, false),
  666. sf.settings("whitelist", loc[5], enableWhitelist, false, enableWhiteList_list),
  667. sf.settings("eventOnly", loc[58], enableEventOnly, false),
  668. sf.settings("wnRefresh", loc[6]+" [v"+wn.vers[1]+"]"),
  669. sf.settings("cleanStorage", loc[7]),
  670. sf.elem("li", "b-settingItem settingCredits settingSeperator", "<p>Version: "+sc.vers+"</p>"),
  671. sf.elem("li", "b-settingItem settingCredits", "<p>"+loc[20]+" <a class='b-orange-arrow' href='"+sc.user.wot+"'>Orrie</a></p>"+((sc.cred[sc.loc]) ? "<p>"+loc[21]+" ("+sc.loc.toUpperCase()+"):</p><table>"+sc.cred[sc.loc]+"</table>" : "")),
  672. 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>")
  673. ];
  674. if (sc.locSup.indexOf(sc.loc) == -1) {
  675. clanSet_list_locItem.innerHTML = "<h1>Script Translation</h1><p>Unsupported language detected!</p><p>If you want to contribute with translation, please contact <a class='b-orange-arrow' href='"+sc.user.wl+"'>Orrie</a></p>";
  676. clanSet_list_items.push(clanSet_list_locItem);
  677. }
  678. else if (locMiss > 0) {
  679. clanSet_list_locItem.innerHTML = "<h1>Script Translation</h1><p>Currently "+locMiss+" out of "+_l+" strings not translated in your language!</p><p>If you want to contribute, open the browser console, translate the strings and send them to <a class='b-orange-arrow' href='"+sc.user.wl+"'>Orrie</a></p>";
  680. clanSet_list_items.push(clanSet_list_locItem);
  681. }
  682. sf.links(clanSet_list, clanSet_list_items);
  683. clanSet_div.firstElementChild.addEventListener('click', function() {this.classList.toggle('cm-user-menu-link__opened'); this.nextSibling.classList.toggle('cm-user-menu__opened');}, false);
  684. clanSet_div.appendChild(clanSet_list);
  685. // add script info and settings if user menu exists, else wait
  686. var navMenu = d.getElementById('common_menu'),
  687. navUser = navMenu.getElementsByClassName('cm-menu__user')[0];
  688. if (navUser) {
  689. navUser.appendChild(clanSet_div);
  690. }
  691. else {
  692. var setLook = new MutationObserver(function() {
  693. navUser = navMenu.getElementsByClassName('cm-menu__user')[0];
  694. navUser.appendChild(clanSet_div);
  695. setLook.disconnect();
  696. });
  697. setLook.observe(navMenu, {childList: true});
  698. }
  699.  
  700. // clan statistic links
  701. var menu_class = d.getElementsByClassName('menu-top')[0],
  702. clanMenu_div = sf.elem("div", "menu-clan_links menu-top_item", "<span class='menu-top_link'>"+loc[1]+"<span class='cm-arrow'></span></span>"),
  703. clanMenu_list = sf.elem("ul", "clan-links cm-sublist", ""),
  704. clanMenu_list_items = [
  705. [sc.srv.wl, "<a target='_blank' href='http://wotlabs.net/"+sc.srv.wl+"/clan/"+wg.clan.name+"'><span class='sl-icon sl-wl'></span>WoTLabs</a>"],
  706. [sc.srv.nm, "<a target='_blank' href='http://noobmeter.com/clan/"+sc.srv.nm+"/"+wg.clan.name+"/"+wg.clan.id+"'><span class='sl-icon sl-nm'></span>Noobmeter</a>"],
  707. [sc.srv.vb, "<a target='_blank' href='http://vbaddict.net/clan/worldoftanks."+sc.srv.vb+"/"+wg.clan.id+"/clan-"+wg.clan.name.toLowerCase()+"'><span class='sl-icon sl-vb'></span>vBAddict</a>"],
  708. [sc.srv.ct, "<a target='_blank' href='http://clantools.us/servers/"+sc.srv.ct+"/clans?id="+wg.clan.id+"'><span class='sl-icon sl-ct'></span>Clan Tools</a>"],
  709. [sc.srv.cs, "<a target='_blank' href='http://wotcs.com/clan.php?wid="+wg.clan.id+"'><span class='sl-icon sl-cs'></span>WoT-CS</a>"],
  710. [sc.srv.kttc, "<a target='_blank' href='http://"+((wg.srv=="ru") ? "" : sc.srv.kttc+".")+"kttc.ru/clan/"+wg.clan.id+"/'><span class='sl-icon sl-kttc'></span>KTTC</a>"],
  711. [sc.srv.wlf, "<a target='_blank' href='http://en.wot-life.com/"+sc.srv.wlf+"/clan/"+wg.clan.name+"-"+wg.clan.id+"/'><span class='sl-icon sl-wlife'></span>WoT-Life</a>"],
  712. [sc.srv.we, "<a target='_blank' href='http://wotevent.guildity.com/clans/"+wg.clan.name+"/'><span class='sl-icon sl-we'></span>WoT Event Stats</a>"],
  713. [sc.srv.wr, "<a target='_blank' href='http://wotreplays."+sc.srv.wr+"/clan/"+wg.clan.name+"'><span class='sl-icon sl-wr'></span>WoTReplays</a>"]
  714. ];
  715. sf.links(clanMenu_list, clanMenu_list_items);
  716. clanMenu_div.firstElementChild.addEventListener('click', function() {this.classList.toggle('cm-parent-link__opened'); this.nextSibling.classList.toggle('cm-sublist__opened');}, false);
  717. clanMenu_div.appendChild(clanMenu_list);
  718. menu_class.appendChild(clanMenu_div);
  719.  
  720. // add clan total stats if they exist
  721. if (wg.p && s.clan) {
  722. var clanProfileValue = d.getElementsByClassName('rating-profile_item');
  723. if (s.clan.win) {
  724. clanProfileValue[1].innerHTML = "<i class='rating-profile_icon i i__rating-common i__wot-victories'></i><span class='rating-profile_value rating-players_stats js-format-number'>"+sf.color(s.clan.win,"wr",2,"%")+"</span><span class='rating-profile_key'>"+loc[8]+"</span>";
  725. }
  726. if (s.clan.wn8) {
  727. clanProfileValue[3].innerHTML = "<i class='rating-profile_icon i i__rating-common i__wot-experience'></i><span class='rating-profile_value rating-players_stats js-format-number'>"+sf.color(s.clan.wn8,"wn8",0)+"</span><span class='rating-profile_key'>"+loc[9]+"</span>";
  728. }
  729. }
  730.  
  731. // check if on memberlist page
  732. if (wg.m) {
  733. // formula calculations and variables
  734. var memObj = {
  735. cls: d.getElementsByClassName('tbl-rating_body')[0],
  736. ids: [],
  737. bans: {ids:[],f:false}
  738. };
  739.  
  740. // add manual stat fetching button
  741. var filter_class = d.getElementsByClassName('filter')[0],
  742. refreshBtn_div = sf.elem("div", "b-button-stats", "<a>"+loc[12]+"</a>");
  743. refreshBtn_div.addEventListener('click', function() {sf.tableFetch();}, false);
  744. filter_class.appendChild(refreshBtn_div);
  745.  
  746. // prepare stat fetcher, store stats in localStorage and reload page
  747. var ratLook = new MutationObserver(function() {
  748. sf.tableFetch();
  749. ratLook.disconnect();
  750. });
  751.  
  752. // fetch stats automatically if enabled or check whitelist for whitelisted clan
  753. if (statFetch && (enableOnPageload || (enableWhitelist && whiteListArray.indexOf(wg.clan.id) > -1))) {
  754. ratLook.observe(memObj.cls, {childList: true});
  755. }
  756. else {
  757. // no stats fetching, check if stats already exist and add if they do
  758. var clanPlayersValue = d.getElementsByClassName('rating-players')[0].rows[0],
  759. pageHeader = d.getElementsByClassName('page-header')[0],
  760. ratHeadStatus = false;
  761. // add clan total stats if they exist
  762. clanPlayersValue.cells[1].getElementsByClassName('rating-players_key')[0].textContent = loc[8];
  763. if (s.clan) {
  764. if (s.clan.win) {
  765. var clanWinCell = clanPlayersValue.insertCell(2);
  766. clanWinCell.className = "rating-players_item rating-players_item__data";
  767. clanWinCell.innerHTML = "<i class='rating-players_icon i i__rating-common i__wot-victories'></i><span class='rating-players_value rating-players_stats'>"+sf.color(s.clan.win,"wr",2,"%")+"</span><span class='rating-players_key'>"+loc[10]+"</span>";
  768. }
  769. if (s.clan.wn8) {
  770. var clanWn8Cell = clanPlayersValue.insertCell(4);
  771. clanWn8Cell.className = "rating-players_item rating-players_item__data";
  772. clanWn8Cell.innerHTML = "<i class='rating-players_icon i i__rating-common i__wot-experience'></i><span class='rating-players_value rating-players_stats'>"+sf.color(s.clan.wn8,"wn8",0)+"</span><span class='rating-players_key'>"+loc[11]+"</span>";
  773. }
  774. }
  775. // add container for member counters
  776. var memInfo_div = sf.elem("div", "page-header_meminfo", "");
  777. pageHeader.appendChild(memInfo_div);
  778. // wait for table to be filled before adding wn8
  779. var ratInsert = new MutationObserver(function(muto) {
  780. if (muto[0].previousSibling === null) {
  781. var newMem = 0, banMem = d.getElementsByClassName('tbl-rating_tr__state-banned').length;
  782. // add a counter for amount of banned people in clan
  783. if (banMem > 0) {
  784. var banMem_span = d.getElementsByClassName('page-header_ban')[0];
  785. if (!banMem_span) {
  786. banMem_span = sf.elem("span", "page-header_ban", loc[17]+" "+banMem);
  787. memInfo_div.appendChild(banMem_span);
  788. }
  789. else {
  790. banMem_span.textContent = loc[17]+" "+banMem;
  791. }
  792. }
  793. // table header for wn8
  794. if (ratHeadStatus === false && Object.keys(s.clan).length !== 0) {
  795. var headName = d.getElementsByClassName('tbl-rating_th__name')[0],
  796. wnHead = sf.elem("td", "tbl-rating_th tbl-rating_th__wn", "<a class='sorter sorter__game-wot js-table-sorter js-sort-wn'><i class='sorter_icon sorter_icon__media i i__table-params i__wot-aeb'></i><span class='sorter_key'>WN8</span><span class='sorter_arrow'></span></a>"),
  797. colGroup = d.getElementsByTagName('colgroup')[0],
  798. newCol = sf.elem("col");
  799. newCol.width = "1px";
  800. headName.parentNode.insertBefore(wnHead, headName.nextSibling);
  801. colGroup.insertBefore(newCol, colGroup.children[5]);
  802. ratHeadStatus = true;
  803. }
  804. // add wn8 for each member and colorize stats
  805. var userCheck = Object.keys(s.user).length !== 0;
  806. for (var _rt=0, _rt_len = memObj.cls.rows.length; _rt<_rt_len; _rt++) {
  807. var row = memObj.cls.rows[_rt];
  808. if (!row.classList.contains("tbl-rating_tr__card")) {
  809. var id = row.getAttribute('data-account_id'),
  810. memName = row.getElementsByClassName('tbl-rating_td__name')[0],
  811. memWGR = row.getElementsByClassName('tbl-rating_td__value')[0],
  812. memWins = row.getElementsByClassName('tbl-rating_td__value')[2];
  813. if (userCheck) {
  814. var wnRow = sf.elem("td", "tbl-rating_td tbl-rating_td__value js-format-number", "");
  815. memName.parentNode.insertBefore(wnRow, memName.nextSibling);
  816. if (s.user[id]) {
  817. wnRow.innerHTML = sf.color(s.user[id].wn8,"wn8",0);
  818. }
  819. else {
  820. wnRow.innerHTML = loc[15];
  821. newMem ++;
  822. }
  823. }
  824. if (memWGR.innerHTML !== "0" && memWGR.innerHTML !== "—") {
  825. memWGR.innerHTML = sf.color(sf.format(memWGR.innerHTML,1),"wgr",0);
  826. }
  827. if (memWins.innerHTML !== "0.00%" && memWins.innerHTML !== "—") {
  828. memWins.innerHTML = sf.color(sf.format(memWins.innerHTML.replace(/[,]/g,"."),3),"wr",2,"%");
  829. }
  830. }
  831. }
  832. // add a counter for new people in the clan, compared to store stats
  833. if (newMem > 0) {
  834. var newMem_span = d.getElementsByClassName('page-header_mem')[0];
  835. if (!newMem_span) {
  836. newMem_span = sf.elem("span", "page-header_mem", loc[16]+" "+newMem);
  837. memInfo_div.appendChild(newMem_span);
  838. }
  839. else {
  840. newMem_span.textContent = loc[16]+" "+newMem;
  841. }
  842. }
  843. // check for length on bans
  844. if (memObj.bans.f) {
  845. sf.apiBanHnd();
  846. }
  847. else {
  848. memObj.bans.cls = d.getElementsByClassName('js-banned');
  849. for (var _bm=0, _bm_len = memObj.bans.cls.length; _bm<_bm_len; _bm++) {
  850. var bannedId = memObj.bans.cls[_bm].dataset.account_id;
  851. memObj.bans.ids.push(bannedId);
  852. }
  853. if (memObj.bans.ids.length > 0) {
  854. sc.api.b = sc.api.i+memObj.bans.ids.join(',')+"&fields=ban_time";
  855. sf.request(sc.api.b , sf.apiBanHnd);
  856. }
  857. }
  858. }
  859. });
  860. ratInsert.observe(memObj.cls, {childList: true});
  861. }
  862. }
  863. else if (wg.g) {
  864. // global variables
  865. var date = new Date();
  866.  
  867. // script variables
  868. var cw_sc = {
  869. cw: {
  870. status: enableEventOnly,
  871. event: false,
  872. fame: 400,
  873. tier: "Ɵ",
  874. bats: "Ɵ",
  875. batsCurr: 0,
  876. batsConc: [],
  877. batsCheck: 0,
  878. elo: "Ɵ",
  879. gold: 0
  880. },
  881. clan: {
  882. id: wg.clan.id,
  883. tag: "Ɵ",
  884. emblem: "Ɵ",
  885. color: "Ɵ"
  886. },
  887. time: {
  888. h: date.getHours(),
  889. m: date.getMinutes(),
  890. o: ((date.getTimezoneOffset() > 0) ? -Math.abs(date.getTimezoneOffset()) : Math.abs(date.getTimezoneOffset()))/60
  891. },
  892. table: {
  893. eu: [17, 18, 19, 20, 21, 22, 23],
  894. na: [23, 0, 1, 2, 3, 4, 5, 6],
  895. ru: [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
  896. c: "",
  897. s: []
  898. },
  899. debug: false
  900. };
  901. cw_sc.api = {
  902. clan: "https://"+wg.srv+".wargaming.net/globalmap/game_api/clan/"+cw_sc.clan.id+"/battles",
  903. divs: "https://"+wg.srv+".wargaming.net/globalmap/game_api/wot/clan_tactical_data",
  904. map: "https://"+wg.srv+".wargaming.net/globalmap/game_api/map_fill_info?aliases=",
  905. tourney: "https://"+wg.srv+".wargaming.net/globalmap/game_api/tournament_info?alias=",
  906. prov: "https://"+wg.srv+".wargaming.net/globalmap/game_api/province_info?alias=",
  907. event: "https://api.worldoftanks."+((wg.srv == "na") ? "com" : wg.srv)+"/wot/globalmap/events/?application_id="+sc.api[wg.srv]+"&limit=1",
  908. provs: "https://api.worldoftanks."+((wg.srv == "na") ? "com" : wg.srv)+"/wot/globalmap/clanprovinces/?application_id="+sc.api[wg.srv]+"&clan_id="+cw_sc.clan.id
  909. };
  910. cw_sc.time.r = ((cw_sc.time.m >= 15 && cw_sc.time.m <= 45) ? [cw_sc.time.h,"30"] : ((cw_sc.time.m <= 15) ? [cw_sc.time.h,"00"] : [(cw_sc.time.h+1),"00"]));
  911. cw_sc.time.t = cw_sc.time.r[0]+"_"+cw_sc.time.r[1];
  912.  
  913. // images, streams and functions
  914. var cw_sf = {
  915. handlerEvent: function(data) { // event checker
  916. // check if active event exists
  917. var event = data.data[0];
  918. if (event.status == "ACTIVE" || !cw_sc.cw.status) {
  919. if (event.status == "ACTIVE") {
  920. cw_sc.cw.event = true;
  921. }
  922. cw_sf.request("mainData", cw_sc.api.clan, cw_sf.handlerMain);
  923. }
  924. else {
  925. // empty table
  926. table.lastElementChild.innerHTML = "";
  927. table.lastElementChild.appendChild(sf.elem("tr", "t-cwText", "<td colspan='8'>"+loc[39]+"</td>"));
  928. clearInterval(updateInterval);
  929. }
  930. // insert update timestamp
  931. d.getElementById('js-batttleUpdate').textContent = new Date().toLocaleTimeString("en-GB");
  932. },
  933. handlerMain: function(data) { // data handler
  934. var battleProvinces = [], battle,
  935. battleFragment = d.createDocumentFragment();
  936. // store data
  937. cw_sc.clan.tag = data.clan.tag;
  938. cw_sc.clan.emblem = data.clan.emblem_url;
  939. cw_sc.clan.color = data.clan.color;
  940. cw_sc.cw.bats = data.clan.appointed_battles_count;
  941. cw_sc.cw.batsCurr = data.battles.length;
  942. cw_sc.cw.elo = {
  943. 6: data.clan.elo_rating_6,
  944. 8: data.clan.elo_rating_8,
  945. 10: data.clan.elo_rating_10
  946. };
  947. style.textContent += ".t-clantag {color: "+cw_sc.clan.color+";}";
  948. // go through battles and planned battles
  949. for (var _b=0, _b_len = data.battles.length; _b<_b_len; _b++) {
  950. battle = data.battles[_b];
  951. if (battleProvinces.indexOf(battle.province_id) == -1) {
  952. battleProvinces.push(battle.province_id);
  953. battleFragment.appendChild(sf.elem("tr", "battle "+battle.province_id, "<td><a class='link__external' target='_blank' href='https://"+wg.srv+".wargaming.net/globalmap/#province/"+battle.province_id+"'>"+battle.province_name+"</a></td><td>"+cw_sf.mapFix(battle.arena_name)+"</td><td></td><td></td><td></td><td></td><td></td><td id='"+battle.enemy.id+"'><a class='link__external' target='_blank' href='http://"+wg.srv+".wargaming.net/clans/"+battle.enemy.id+"/globalmap'><span style='color: "+battle.enemy.color+";'>["+battle.enemy.tag+"]</span> <img src='"+battle.enemy.emblem_url+"'></a></td><td class='t-battle'>Ɵ</td><td class='t-battle t-border'>Ɵ</td>"+cw_sc.table.c));
  954. }
  955. }
  956. for (var _bp=0, _bp_len = data.planned_battles.length; _bp<_bp_len; _bp++) {
  957. battle = data.planned_battles[_bp];
  958. if (battleProvinces.indexOf(battle.province_id) == -1) {
  959. battleProvinces.push(battle.province_id);
  960. battleFragment.appendChild(sf.elem("tr", "battle planned "+battle.province_id, "<td><a class='link__external' target='_blank' href='https://"+wg.srv+".wargaming.net/globalmap/#province/"+battle.province_id+"'>"+battle.province_name+"</a></td><td>"+cw_sf.mapFix(battle.arena_name)+"</td><td></td><td>"+((cw_sc.cw.event) ? "" : battle.province_revenue)+"</td><td></td><td></td><td></td><td>"+loc[40]+"</td><td class='t-battle'>Ɵ</td><td class='t-battle t-border'>Ɵ</td>"+cw_sc.table.c));
  961. }
  962. }
  963. // show foes and battle count if clan has any battles and remove loading indicator
  964. if (cw_sc.cw.bats > 0) {
  965. style.textContent += ".t-battle {display: table-cell !important;}";
  966. if (table.rows[1] && table.rows[1].classList.contains("t-cwText")) {
  967. table.lastElementChild.innerHTML = ""; // empty table
  968. }
  969. }
  970. table.lastElementChild.appendChild(battleFragment);
  971. // insert battle count
  972. d.getElementById('js-battles').textContent = cw_sc.cw.bats;
  973. // send request for detailed battle information
  974. cw_sf.request("batsData", cw_sc.api.map+battleProvinces.join("&aliases="), cw_sf.handlerBats);
  975. },
  976. handlerBats: function(data) { // battles handler
  977. for (var _bd=0, _bd_len = data.data.length; _bd<_bd_len; _bd++) {
  978. var battle = data.data[_bd],
  979. battleRow = d.getElementsByClassName(battle.alias)[0],
  980. enemyID = battleRow.children[7].id,
  981. battleType = ((battle.owner_clan_id == cw_sc.clan.id) ? loc[43] : ((battle.owner_clan_id == enemyID) ? loc[44] : loc[45])),
  982. primeTime = [cw_sf.time(parseFloat(battle.primetime.match(/\d+/g)[0])), battle.primetime.match(/\d+/g)[1], parseFloat(battle.primetime.match(/\d+/g)[0])];
  983. // modify cells cells
  984. battleRow.children[2].textContent = primeTime[0]+":"+primeTime[1];
  985. battleRow.children[2].dataset.sort = primeTime[2];
  986. battleRow.children[3].innerHTML = (cw_sc.cw.event) ? battle.display_fame_points : "<span class='gold'>"+battle.revenue+"</span>";
  987. battleRow.children[5].textContent = battle.owner_clan_rating;
  988. battleRow.children[6].textContent = battleType;
  989. // get correct battle count and schedule
  990. cw_sf.request("tourneyData", cw_sc.api.tourney+battle.alias+"&round=1", cw_sf.handlerTourney);
  991. }
  992. // send request for clan provinces
  993. cw_sf.request("provData", cw_sc.api.provs+"&round=1", cw_sf.handlerProv);
  994. // refresh table
  995. sortTable.refresh();
  996. },
  997. handlerTourney: function(data) { // tournament handler
  998. var battleRow = d.getElementsByClassName(data.province_id)[0],
  999. primeTime = [cw_sf.time(parseFloat(data.start_time.match(/\d+/g)[0])), data.start_time.match(/\d+/g)[1], parseFloat(data.start_time.match(/\d+/g)[0])],
  1000. ownerClan = (data.owner) ? (data.owner.id == cw_sc.clan.id) || false : false,
  1001. cellOwnerTime = false,
  1002. provFame = cw_sc.cw.fame*((data.owner) ? (Math.floor(data.owner.occupy/24)+1) : 1),
  1003. attackers = [data.pretenders, 0];
  1004. cw_sc.cw.batsCheck ++;
  1005. // check attackers
  1006. if (data.is_superfinal) {
  1007. attackers = 1;
  1008. }
  1009. else if (attackers[0]) {
  1010. attackers = attackers[0].length;
  1011. }
  1012. else {
  1013. for (var _bc=0, _bc_len = data.battles.length; _bc<_bc_len; _bc++) {
  1014. attackers[1] += ((data.battles[_bc].is_fake) ? 1 : 2);
  1015. }
  1016. attackers = attackers[1];
  1017. }
  1018. // find how many battles
  1019. var battles = (attackers !== 0) ? Math.ceil(Math.log2(attackers))+1 : 0;
  1020. // modify cells
  1021. battleRow.children[1].textContent = cw_sf.mapFix(data.arena_name);
  1022. battleRow.children[2].textContent = primeTime[0]+":"+primeTime[1];
  1023. battleRow.children[3].innerHTML = (cw_sc.cw.event) ? provFame : "<span class='gold'>"+data.province_revenue+"</span>";
  1024. battleRow.children[4].innerHTML = (data.owner) ? "<a class='link__external' target='_blank' href='http://"+wg.srv+".wargaming.net/clans/"+data.owner.id+"/globalmap'><span style='color: "+data.owner.color+";'>["+data.owner.tag+"]</span> <img src='"+data.owner.emblem_url+"'></a>" : loc[47];
  1025. if (ownerClan) {
  1026. cw_sc.cw.gold += data.province_revenue;
  1027. d.getElementById('js-gold').textContent = sf.format(cw_sc.cw.gold,2); // insert gold count
  1028. if (cw_sc.cw.tier !== "Ɵ") {
  1029. battleRow.children[5].textContent = data.owner["elo_rating_"+cw_sc.cw.tier];
  1030. }
  1031. }
  1032. // only continue if there are any attackers
  1033. if (attackers) {
  1034. var cellEmpty = {
  1035. eu: {20:15, 19:13, 18:11, 17:9},
  1036. na: {3:17, 2:15, 1:13, 0:11, 23:9},
  1037. ru: {20:31, 19:29, 18:27, 17:25, 16:23, 15:21, 14:19, 13:17, 12:15, 11:13, 10:11, 9:9},
  1038. },
  1039. lastBattle = battles+cellEmpty[wg.srv][primeTime[2]];
  1040. battleRow.children[8].textContent = attackers;
  1041. battleRow.children[9].textContent = battles;
  1042. for (var _e=10; _e<battleRow.childElementCount; _e++) {
  1043. var cell = battleRow.children[_e];
  1044. if (_e > cellEmpty[wg.srv][primeTime[2]] && _e <= lastBattle) {
  1045. var timeClass = "."+cell.classList.item(1),
  1046. timePrevClass = "."+cell.previousElementSibling.classList.item(1);
  1047. if (cw_sc.table.s.indexOf(timeClass) == -1 || cw_sc.table.s.indexOf(timePrevClass) == -1) {
  1048. cw_sc.table.s.push(timePrevClass, timeClass);
  1049. if (_e == lastBattle) {
  1050. cw_sc.table.s.push(timePrevClass+" + th", timePrevClass+" + td", timeClass+" + th", timeClass+" + td");
  1051. }
  1052. }
  1053. if (ownerClan && _e !== lastBattle) {
  1054. cell.className += " t-noFight";
  1055. }
  1056. else {
  1057. cell.className += " t-fight";
  1058. if (cw_sc.cw.batsConc[_e]) {
  1059. cw_sc.cw.batsConc[_e] ++;
  1060. }
  1061. else {
  1062. cw_sc.cw.batsConc[_e] = 1;
  1063. }
  1064. }
  1065. if (_e == lastBattle) {
  1066. if (ownerClan) {
  1067. cell.className += " js-last";
  1068. }
  1069. if (!data.owner) {
  1070. cell.className += " t-noOwner";
  1071. }
  1072. cell.innerHTML = "♖";
  1073. cellOwnerTime = [parseFloat(cell.classList.item(1).match(/\d+/g)[0]), parseFloat(cell.classList.item(1).match(/\d+/g)[1])];
  1074. }
  1075. else {
  1076. cell.innerHTML = "&#9876;";
  1077. }
  1078. }
  1079. }
  1080. if (cw_sc.cw.batsCheck == cw_sc.cw.bats) {
  1081. d.getElementById('js-battlesConc').textContent = cw_sc.cw.batsConc.sort(function(a,b){return b-a;})[0];
  1082. style.textContent += cw_sc.table.s.join(", ")+" {display: table-cell !important;}";
  1083. }
  1084. // check if battle is planned or not started and change state to ongoing
  1085. if (battleRow.children[6].innerHTML == loc[42] && new Date().getHours() >= primeTime[0]-1 && new Date().getHours() < cellOwnerTime[0]) {
  1086. battleRow.children[6].textContent = loc[43];
  1087. battleRow.children[7].textContent = loc[41];
  1088. }
  1089. // check if no opponent - free round
  1090. var lastBattle = data.battles[data.battles.length-1];
  1091. if (battleRow.children[7].innerHTML == loc[40] && lastBattle && lastBattle.is_fake && lastBattle.first_competitor.id == cw_sc.clan.id) {
  1092. battleRow.children[7].textContent = loc[46];
  1093. battleRow.children[7].classList.add("t-bold");
  1094. }
  1095. }
  1096. else {
  1097. battleRow.children[8].textContent = "ERROR";
  1098. battleRow.children[8].classList.add("t-error");
  1099. }
  1100. // refresh table
  1101. battleRow.children[2].dataset.sort = primeTime[2]+"."+((battleRow.children[6].innerHTML == loc[45]) ? 0+""+battles : 1+""+cellOwnerTime[0]+""+cellOwnerTime[1]);
  1102. sortTable.refresh();
  1103. },
  1104. handlerProv: function(data) { // provinces handler
  1105. var provs = data.data[cw_sc.clan.id],
  1106. provFragment = d.createDocumentFragment();
  1107. if (table.rows[1] && table.rows[1].classList.contains("t-cwText")) {
  1108. table.lastElementChild.innerHTML = ""; // empty table
  1109. }
  1110. if (provs) {
  1111. for (var _p=0, _p_len = provs.length; _p<_p_len; _p++) {
  1112. var prov = provs[_p],
  1113. battleRow = d.getElementsByClassName(prov.province_id)[0],
  1114. primeTime = [cw_sf.time(parseFloat(prov.prime_time.match(/\d+/g)[0])), prov.prime_time.match(/\d+/g)[1]],
  1115. provFame = 400*(Math.floor(prov.turns_owned/24)+1);
  1116. if (!battleRow) {
  1117. provFragment.appendChild(sf.elem("tr", "province "+prov.province_id, "<td><a class='link__external' target='_blank' href='https://"+wg.srv+".wargaming.net/globalmap/#province/"+prov.province_id+"'>"+prov.province_name+"</a></td><td>"+cw_sf.mapFix(prov.arena_name)+"</td><td data-sort='"+(primeTime[0]+10)+"'>"+primeTime[0]+":"+primeTime[1]+"</td><td>"+((cw_sc.cw.event) ? provFame : "<span class='gold'>"+prov.daily_revenue+"</span>")+"</td><td><a class='link__external' target='_blank' href='http://"+wg.srv+".wargaming.net/clans/"+cw_sc.clan.id+"/globalmap'><span class='t-clantag'>["+cw_sc.clan.tag+"]</span> <img src='"+cw_sc.clan.emblem+"'></a></td><td>"+cw_sc.cw.elo[prov.max_vehicle_level]+"</td><td>"+loc[43]+"</td><td>"+loc[48]+"</td><td class='t-battle' data-sort='99'>Ɵ</td><td class='t-battle t-border' data-sort='99'>Ɵ</td>"+cw_sc.table.c));
  1118. cw_sc.cw.gold += prov.daily_revenue;
  1119. cw_sc.cw.tier = prov.max_vehicle_level;
  1120. }
  1121. }
  1122. // insert gold count
  1123. d.getElementById('js-gold').textContent = sf.format(cw_sc.cw.gold,2);
  1124. // send request for divisions
  1125. cw_sf.request("divsData", cw_sc.api.divs, cw_sf.handlerDivs);
  1126. }
  1127. else if (cw_sc.cw.bats === 0) {
  1128. provFragment.appendChild(sf.elem("tr", "t-cwText", "<td colspan='8'>"+loc[49]+"</td>"));
  1129. }
  1130. table.lastElementChild.appendChild(provFragment);
  1131. // refresh table
  1132. sortTable.refresh();
  1133. },
  1134. handlerDivs: function(data) { // divisions handler
  1135. if (data.data[0].division.clan_id == cw_sc.clan.id) {
  1136. for (var _p=0, _p_len = data.data.length; _p<_p_len; _p++) {
  1137. var div = data.data[_p],
  1138. battleRow = d.getElementsByClassName(div.alias)[0];
  1139. if (!div.division && battleRow.classList.contains('province')) {
  1140. var defBattle = battleRow.getElementsByClassName("js-last")[0];
  1141. battleRow.children[7].textContent = loc[50];
  1142. battleRow.children[7].classList.add("t-bold");
  1143. if (defBattle) {
  1144. defBattle.classList.remove("t-fight");
  1145. defBattle.classList.add("t-noFight");
  1146. }
  1147. }
  1148. else {
  1149. // sometimes future defenses wont show up in planned battles
  1150. if (div.attackers.length > 0 && battleRow.classList.contains('province')) {
  1151. table.lastElementChild.appendChild(sf.elem("tr", "planned "+div.alias, "<td><a class='link__external' target='_blank' href='https://"+wg.srv+".wargaming.net/globalmap/#province/"+div.alias+"'>"+div.name+"</a></td><td></td><td></td><td>"+battleRow.children[3].innerHTML+"</td><td></td><td></td><td></td><td>"+loc[42]+"</td>"));
  1152. battleRow.parentNode.removeChild(battleRow);
  1153. cw_sf.request("tourneyData", cw_sc.api.tourney+div.alias+"&round=1", cw_sf.handlerTourney);
  1154. // refresh table
  1155. sortTable.refresh();
  1156. }
  1157. }
  1158. }
  1159. }
  1160. else {
  1161. d.getElementById('js-error').textContent = " • "+loc[51];
  1162. }
  1163. },
  1164. handlerError: function(name, data) { // error handler
  1165. if (cw_sc.debug) {console.info("errorData", name, data);}
  1166. switch(name) {
  1167. case ("mainData"):
  1168. table.lastElementChild.appendChild(sf.elem("tr", "t-cwText", "<td colspan='8'>"+loc[52]+"</td>"));
  1169. break;
  1170. case ("divsData"):
  1171. d.getElementById('js-error').textContent = " • "+loc[51];
  1172. break;
  1173. default: break;
  1174. }
  1175. },
  1176. time: function (hour, min, type) { // time converter
  1177. var time = hour+cw_sc.time.o;
  1178. if (time >= 24) {
  1179. time -= 24;
  1180. }
  1181. else if (time <= 0) {
  1182. time += 24;
  1183. }
  1184. if (type == "s") {
  1185. time = "t-"+time+"_"+min+((time === 0 && min == "00") ? " t-24_00" : "");
  1186. }
  1187. return time;
  1188. },
  1189. timer: function () { // timestamp handler
  1190. var dateNow = new Date(),
  1191. time = {
  1192. h: cw_sf.time(cw_sc.table[wg.srv][0]-1)-dateNow.getHours(),
  1193. m: 60-dateNow.getMinutes()-1,
  1194. s: 60-dateNow.getSeconds()-1
  1195. };
  1196. var timeSpan = d.getElementById('js-timePrime');
  1197. if (!cw_sc.cw.event && cw_sc.cw.status) {
  1198. timeSpan.textContent = loc[53];
  1199. timeSpan.classList.add("t-bold");
  1200. clearInterval(timeInterval);
  1201. }
  1202. else if (time.h >= 0 && (time.s > 0 || time.m > 0)) {
  1203. timeSpan.textContent = ((time.h > 0) ? time.h+" "+loc[55]+", " : "")+((time.m > 0) ? time.m+" "+loc[56]+", " : "")+time.s+" "+loc[57];
  1204. }
  1205. else if (time.h < 0) {
  1206. if (cw_sc.cw.bats == "Ɵ") {
  1207. if (cw_sc.cw.bats === 0) {
  1208. timeSpan.textContent = loc[54];
  1209. timeSpan.classList.add("t-bold");
  1210. clearInterval(timeInterval);
  1211. }
  1212. }
  1213. else {
  1214. timeSpan.classList.add("h-shadow");
  1215. timeSpan.textContent = loc[59];
  1216. if (cw_sc.cw.batsCurr > 0) {
  1217. d.getElementById('js-provStatus').textContent = loc[61];
  1218. }
  1219. clearInterval(timeInterval);
  1220. }
  1221. }
  1222. },
  1223. mapFix: function(name) { // map name fixer
  1224. var fixedNames = {
  1225. "114_czech/name": "Pilsen"
  1226. };
  1227. return (fixedNames[name]) ? fixedNames[name] : name;
  1228. },
  1229. updater: function () { // updater handler
  1230. var newTime = ((cw_sc.time.m >= 15 && cw_sc.time.m <= 45) ? [cw_sc.time.h,"30"] : ((cw_sc.time.m <= 15) ? [cw_sc.time.h,"00"] : [(cw_sc.time.h+1),"00"]));
  1231. if (cw_sc.time.r[0] !== newTime[0] || cw_sc.time.r[1] !== newTime[1]) {
  1232. cw_sf.request("mainData", cw_sc.api.clan, cw_sf.handlerMain);
  1233. }
  1234. },
  1235. request: function (name, api, handler) { // request handler
  1236. // GreaseMonkey xmlhttpRequest
  1237. GM_xmlhttpRequest({
  1238. method: "GET",
  1239. url: api,
  1240. headers: {
  1241. Accept: "application/json"
  1242. },
  1243. onload: function(resp) {
  1244. var data = JSON.parse(resp.responseText);
  1245. if (resp.status == 200) {
  1246. if (cw_sc.debug) {console.info(name, data);}
  1247. handler(data);
  1248. }
  1249. else {
  1250. cw_sf.handlerError(name, resp);
  1251. }
  1252. },
  1253. onerror: function(resp) {
  1254. console.error("Error accessing Wargaming API", name, api, resp);
  1255. }
  1256. });
  1257. }
  1258. };
  1259.  
  1260. // inserting style into head
  1261. var cw_style = sf.elem("style", "wotstatscript", "", "text/css"),
  1262. styleText = [
  1263. "h3 {text-align: center;}",
  1264. ".b-battles {font-size: 12px; margin: 0px 0 60px; width: 100%;}",
  1265. ".b-battles .h-battles {font-size: 15px; position: relative;}",
  1266. ".b-battles .h-battles .h-battles-info {border-bottom: 1px solid #000; box-shadow: inset 0 -1px rgba(255,255,255,.05); text-align: center; padding: 10px 0;}",
  1267. ".b-battles .h-battles .h-battles-info img {max-height: 16px; vertical-align: bottom;}",
  1268. ".b-battles .h-battles .h-battles-info .h-shadow {font-weight: bold; text-shadow: 0px 0px 1px rgba(27,27,28, 1), 0px 0px 2px rgba(27,27,28, 1);}",
  1269. ".b-battles .h-battles .h-battles-infotable {margin: 21px 10px; min-width: 150px; position: absolute; top: 0px;}",
  1270. ".b-battles .h-battles .h-battles-infotable td {padding: 0 2px;}",
  1271. ".b-battles .h-battles .h-battles-infotable td.gold {padding-right: 16px;}",
  1272. ".b-battles .b-battles-holder {background-color: rgba(0, 0, 0, 0.75);}",
  1273. ".b-battles .b-battles-holder .t-battles {border-spacing: 0; box-shadow: inset -1px 0 rgba(255,255,255,.05); text-align: center; width: 100%;}",
  1274. ".b-battles .b-battles-holder .t-battles thead tr {}",
  1275. ".b-battles .b-battles-holder .t-battles tbody tr:nth-child(even) td {background-color: rgba(80, 60, 60, 0.1);}",
  1276. ".b-battles .b-battles-holder .t-battles tbody tr:nth-child(odd) td {background-color: rgba(123, 123, 123, 0.1);}",
  1277. ".b-battles .b-battles-holder .t-battles tbody tr:hover {background-color: rgba(100, 100, 100, 0.20);}",
  1278. ".b-battles .b-battles-holder .t-battles thead tr th.t-"+cw_sc.time.t+", .b-battles .b-battles-holder .t-battles tbody tr td.t-"+cw_sc.time.t+" {background-color: rgba(254,252,223, 0.15); border-left: 1px solid #808080; border-right: 1px solid #808080;}",
  1279. ".b-battles .b-battles-holder .t-battles thead tr th.t-"+cw_sc.time.t+" + th, .b-battles .b-battles-holder .t-battles tbody tr td.t-"+cw_sc.time.t+" + td {background-color: rgba(224,223,218, 0.1); border-right: 1px solid #808080;}",
  1280. ".b-battles .b-battles-holder .t-battles tr .t-border {border-right: 2px solid rgba(194, 173, 173, 0.1);}",
  1281. ".b-battles .b-battles-holder .t-battles tr th {line-height: 35px; border-top: 1px solid rgba(255,255,255,.1); border-bottom: 1px solid #000; box-shadow: inset 1px -1px rgba(255,255,255,.05); position: relative;}",
  1282. ".b-battles .b-battles-holder .t-battles tr th .sorter_arrow {background: url(http://eu.wargaming.net/clans/static/2.4.2/images/sorter/sorter-wot.png) no-repeat 50% 0; margin-top: -3px; width: 100%; left: 0;}",
  1283. ".b-battles .b-battles-holder .t-battles tr th:hover {color: #FFFFFF;}",
  1284. ".b-battles .b-battles-holder .t-battles tr th:hover .sorter_arrow {opacity: 1;}",
  1285. ".b-battles .b-battles-holder .t-battles tr th.sort-up, .b-battles .b-battles-holder .t-battles tr th.sort-down {color: #DADADB;}",
  1286. ".b-battles .b-battles-holder .t-battles tr th.sort-up .sorter_arrow {background-position-y: -10px; margin-top: -5px; opacity: 1;}",
  1287. ".b-battles .b-battles-holder .t-battles tr th.sort-down .sorter_arrow {background-position-y: -5px; opacity: 1;}",
  1288. ".b-battles .b-battles-holder .t-battles tr td {line-height: 25px; border-top: 1px solid rgba(255,255,255,.1); border-bottom: 1px solid #000; box-shadow: inset 1px -1px rgba(255,255,255,.05); padding: 0 2px;}",
  1289. ".b-battles .b-battles-holder .t-battles tr td:first-of-type {max-width: 125px; width: 125px; overflow: hidden; padding: 0 5px; text-overflow: ellipsis; white-space: nowrap;}",
  1290. ".b-battles .b-battles-holder .t-battles tr td.t-title {font-weight: bold;}",
  1291. ".b-battles .b-battles-holder .t-battles tr td.t-good {color: #4D7326;}",
  1292. ".b-battles .b-battles-holder .t-battles tr td.t-bad {color: #930D0D;}",
  1293. ".b-battles .b-battles-holder .t-battles tr td.t-plan {color: #FFE400;}",
  1294. ".b-battles .b-battles-holder .t-battles tr td.t-fight {color: #4D7326; font-size: 15px; font-weight: bold;}",
  1295. ".b-battles .b-battles-holder .t-battles tr td.t-noFight {color: #808080; font-size: 14px;}",
  1296. ".b-battles .b-battles-holder .t-battles tr td.t-fight.t-noOwner {color: #808080;}",
  1297. ".b-battles .b-battles-holder .t-battles tr td.t-error {color: #CD2911;}",
  1298. ".b-battles .b-battles-holder .t-battles tr.t-cwText td {font-size: 26px; line-height: 54px;}",
  1299. ".b-battles .b-battles-holder .t-battles img {height: 16px; margin-bottom: 5px; vertical-align: bottom;}",
  1300. ".b-battles .f-battles {border-top: 1px solid #000; box-shadow: inset 0 1px rgba(255,255,255,.05); font-size: 15px; padding: 10px 0; text-align: center;}",
  1301. ".b-battles .f-battles img {max-height: 16px; vertical-align: bottom;}",
  1302. ".b-battles .t-bold {font-weight: bold;}",
  1303. ".t-battle {display: none;}",
  1304. ".t-time {display: none;}",
  1305. ".b-display-none {display: none;}",
  1306. ".b-display-block {display: block}"
  1307. ];
  1308. cw_style.textContent = styleText.join("");
  1309. d.head.appendChild(cw_style);
  1310.  
  1311. // prepare static html and table reference for further use
  1312. var widgets = d.getElementsByClassName("widgets")[0],
  1313. battlesPanel = sf.elem("div", "b-battles", "<div class='h-battles'><h3>"+loc[22]+"</h3><div class='h-battles-info'>"+loc[23]+" <span id='js-timePrime'>Ɵ</span></div><table class='h-battles-infotable'><tr><td>"+loc[24]+"</td><td id='js-battles'>0</td><td>"+loc[60]+"</td><td id='js-battlesConc'>0</td></tr><tr><td>"+loc[25]+"</td><td class='gold' id='js-gold'>0</td></tr></table></div><div class='b-battles-holder'><table class='t-battles sortable'><thead><tr><th>"+loc[26]+"<span class='sorter_arrow'></span></th><th>"+loc[27]+"<span class='sorter_arrow'></span></th><th id='js-sort' class='sort-default' data-sort-order='desc'>"+loc[28]+"<span class='sorter_arrow'></span></th><th>"+((cw_sc.cw.event) ? loc[29] : loc[30])+"<span class='sorter_arrow'></span></th><th>"+loc[31]+"<span class='sorter_arrow'></span></th><th>"+loc[32]+"<span class='sorter_arrow'></span></th><th>"+loc[33]+"<span class='sorter_arrow'></span></th><th id='js-provStatus'>"+loc[34]+"<span class='sorter_arrow'></span></th><th class='t-battle'>"+loc[35]+"<span class='sorter_arrow'></span></th><th class='t-battle t-border'>"+loc[36]+"<span class='sorter_arrow'></span></th></tr></thead><tbody></tbody></table></div><div class='f-battles'>"+loc[37]+" <span id='js-batttleUpdate'>Ɵ</span> [UTC"+((cw_sc.time.o >= 0) ? "+" : "")+cw_sc.time.o+"]<span id='js-error'></span></div>"),
  1314. table = battlesPanel.children[1].firstElementChild,
  1315. widgetsLook = new MutationObserver(function() {
  1316. widgets.insertBefore(battlesPanel, widgets.children[1]);
  1317. widgetsLook.disconnect();
  1318. });
  1319. //widgets.insertBefore(battlesPanel, widgets.children[2]);
  1320. widgetsLook.observe(widgets, {childList: true});
  1321.  
  1322. // time cells for header and body rows
  1323. var timeCells = cw_sc.table[wg.srv],
  1324. timeFragment = d.createDocumentFragment();
  1325. for (var _tc=0, _tc_len = timeCells.length; _tc<_tc_len; _tc++) {
  1326. var t = timeCells[_tc],
  1327. times = [cw_sf.time(t,"00","s"), cw_sf.time(t)+":00", cw_sf.time(t,"30","s"), cw_sf.time(t)+":30"];
  1328. timeFragment.appendChild(sf.elem("th", "t-time "+times[0], times[1]+"<span class='sorter_arrow'></span>"));
  1329. cw_sc.table.c += "<td class='t-time "+times[0]+"'></td>";
  1330. if (_tc !== _tc_len-1) {
  1331. timeFragment.appendChild(sf.elem("th", "t-time "+times[2], times[3]+"<span class='sorter_arrow'></span>"));
  1332. cw_sc.table.c += "<td class='t-time "+times[2]+"'></td>";
  1333. }
  1334. }
  1335. table.firstElementChild.firstElementChild.appendChild(timeFragment);
  1336.  
  1337. // add intervals for time and round updater
  1338. var timeInterval = setInterval(cw_sf.timer,1000), // 1 second
  1339. updateInterval = setInterval(cw_sf.updater,120000); // 2 minutes
  1340.  
  1341. // activate tablesort function
  1342. var sortTable = false;
  1343. if (Tablesort) {
  1344. // Numeric sort
  1345. Tablesort.extend('number', function(item) {
  1346. return item.match(/^-?(\d)*-?([,\.]){0,1}-?(\d)+([E,e][\-+][\d]+)?%?$/); // Number
  1347. }, function(a, b) {
  1348. a = parseFloat(a);
  1349. b = parseFloat(b);
  1350.  
  1351. a = isNaN(a) ? 0 : a;
  1352. b = isNaN(b) ? 0 : b;
  1353. return a - b;
  1354. });
  1355. sortTable = new Tablesort(table);
  1356. }
  1357. else {
  1358. window.alert("Error activating tablesort, please refresh - if this shit continues, poke Orrie");
  1359. }
  1360.  
  1361. // insert update status
  1362. table.lastElementChild.appendChild(sf.elem("tr", "t-cwText", "<td colspan='8'>"+loc[38]+"</td>"));
  1363.  
  1364. // send request to wargaming api to see if an event is running
  1365. cw_sf.request("eventData", cw_sc.api.event, cw_sf.handlerEvent);
  1366. }
  1367. }(window));

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址