TMVN Club Transfer

Trophymanager: transfer statistics of all seasons, the most expensive players, the most successful trades, revenue from the academy... It made by request of Vasco Vitkovice, Tirana Smokers, Bones and Langevåg IL.

  1. // ==UserScript==
  2. // @name TMVN Club Transfer
  3. // @namespace https://trophymanager.com
  4. // @version 13
  5. // @description Trophymanager: transfer statistics of all seasons, the most expensive players, the most successful trades, revenue from the academy... It made by request of Vasco Vitkovice, Tirana Smokers, Bones and Langevåg IL.
  6. // @include https://trophymanager.com/club/*
  7. // @include https://trophymanager.com/club/*/
  8. // @exclude https://trophymanager.com/club/
  9. // @exclude https://trophymanager.com/club/*/squad/
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. 'use strict';
  15.  
  16. const APPLICATION_PARAM = {
  17. DEFAULT_TOP_COUNT: 10,
  18. TOP_COUNT_LOCAL_STORAGE_KEY: "TMVN_CLUB_TRANSFER_TOP_COUNT",
  19. DEFAULT_SEASON_COUNT: 0,
  20. SEASON_COUNT_LOCAL_STORAGE_KEY: "TMVN_CLUB_TRANSFER_SEASON_COUNT",
  21. TO_SEASON_LOCAL_STORAGE_KEY: "TMVN_CLUB_TRANSFER_TO_SEASON",
  22. MIN_PROFIT_LOCAL_STORAGE_KEY: "TMVN_CLUB_TRANSFER_MIN_PROFIT",
  23. DEFAULT_MIN_PROFIT: -999999,
  24. MAX_PROFIT_LOCAL_STORAGE_KEY: "TMVN_CLUB_TRANSFER_MAX_PROFIT",
  25. DEFAULT_MAX_PROFIT: 999999,
  26. DEFAULT_SHOW_MODE: "11111",
  27. SHOW_MODE_LOCAL_STORAGE_KEY: "TMVN_CLUB_TRANSFER_SHOW_MODE",
  28. SEASON_SHOW: 2
  29. }
  30. const CLASS_NAME = {
  31. SUMMARY_TRANSFER: 'tmvn_club_transfer_script_classname_summary_transfer',
  32. ACADEMY_REVENUE: 'tmvn_club_transfer_script_classname_academy_revenue'
  33. }
  34. const CONTROL_ID = {
  35. INPUT_SHOW_MODE: 'tmvn_club_transfer_script_input_show_mode',
  36. BUTTON_SHOW_MODE: 'tmvn_club_transfer_script_button_show_mode_set',
  37. INPUT_TOP_COUNT: 'tmvn_club_transfer_script_input_top_count',
  38. BUTTON_TOP_COUNT: 'tmvn_club_transfer_script_button_top_count_set',
  39. INPUT_SEASON_COUNT: 'tmvn_club_transfer_script_input_season_count',
  40. INPUT_TO_SEASON: 'tmvn_club_transfer_script_input_to_season',
  41. BUTTON_SEASON_COUNT: 'tmvn_club_transfer_script_button_season_count_set',
  42. BUTTON_SHOW_ALL_SUMMARY_TRANSFER: 'tmvn_club_transfer_script_button_show_all_summary_transfer',
  43. BUTTON_SHOW_ALL_ACADEMY_REVENUE: 'tmvn_club_transfer_script_button_show_all_academy_revenue',
  44. INPUT_MIN_PROFIT: 'tmvn_club_transfer_script_input_min_profit',
  45. INPUT_MAX_PROFIT: 'tmvn_club_transfer_script_input_max_profit',
  46. BUTTON_TRADE_PROFIT: 'tmvn_club_transfer_script_button_trade_profit_set',
  47. }
  48. const APPLICATION_COLOR = {
  49. AVERAGE: 'Aqua',
  50. TOTAL: 'Yellow',
  51. ONSQUAD: 'Blue',
  52. }
  53.  
  54. var topCount,
  55. seasonCount,
  56. toSeason,
  57. minProfit,
  58. maxProfit,
  59. totalTradeBuy,
  60. totalTradeSell,
  61. totalTradeProfit,
  62. totalSquadBuy,
  63. squadCount;
  64.  
  65. seasonCount = localStorage.getItem(APPLICATION_PARAM.SEASON_COUNT_LOCAL_STORAGE_KEY);
  66. if (seasonCount == null || seasonCount == "") {
  67. seasonCount = APPLICATION_PARAM.DEFAULT_SEASON_COUNT;
  68. }
  69.  
  70. minProfit = localStorage.getItem(APPLICATION_PARAM.MIN_PROFIT_LOCAL_STORAGE_KEY);
  71. if (minProfit == null || minProfit == "") {
  72. minProfit = APPLICATION_PARAM.DEFAULT_MIN_PROFIT;
  73. }
  74. maxProfit = localStorage.getItem(APPLICATION_PARAM.MAX_PROFIT_LOCAL_STORAGE_KEY);
  75. if (maxProfit == null || maxProfit == "") {
  76. maxProfit = APPLICATION_PARAM.DEFAULT_MAX_PROFIT;
  77. }
  78.  
  79. var boughtArr = [];
  80. var soldArr = [];
  81. var tradeArr = [];
  82. var academySoldMap = new Map();
  83. var academySummary = [];
  84. var transferSummary = [];
  85. var squadPlayerIdArr = [];
  86. var playerMap = new Map();
  87. var loadCount = 0;
  88. var loadDone = false;
  89. var clubId = location.href.split('/')[4];
  90. var seasonIds = [];
  91. $.ajaxSetup({
  92. async: false
  93. });
  94. $.ajax('https://trophymanager.com/history/club/transfers/' + clubId, {
  95. type: "GET",
  96. dataType: 'html',
  97. crossDomain: true,
  98. success: function (response) {
  99. let comboSeason = $('#stats_season', response)[0].options;
  100. for (let i = 0; i < comboSeason.length; i++) {
  101. seasonIds.push(comboSeason[i].value);
  102. }
  103. },
  104. error: function (e) {}
  105. });
  106.  
  107. $.ajax('https://trophymanager.com/club/' + clubId + '/squad/', {
  108. type: "GET",
  109. dataType: 'html',
  110. crossDomain: true,
  111. success: function (response) {
  112. let player = $('a[player_link]', response);
  113. for (let i = 0; i < player.length; i++) {
  114. squadPlayerIdArr.push(player[i].getAttribute('player_link'));
  115. }
  116. },
  117. error: function (e) {}
  118. });
  119. $.ajaxSetup({
  120. async: true
  121. });
  122. if (seasonCount > 0 && seasonCount < seasonIds.length) {
  123. toSeason = localStorage.getItem(APPLICATION_PARAM.TO_SEASON_LOCAL_STORAGE_KEY);
  124. if (toSeason == null || toSeason == "") {
  125. do {
  126. seasonIds.pop();
  127. } while (seasonCount < seasonIds.length);
  128. } else {
  129. let fromSeason = toSeason - seasonCount + 1;
  130. while (fromSeason > seasonIds[seasonIds.length - 1]) {
  131. seasonIds.pop();
  132. }
  133. while (toSeason < seasonIds[0]) {
  134. seasonIds.shift();
  135. }
  136. }
  137. }
  138.  
  139. if (clubId != "" && seasonIds.length > 0) {
  140. seasonIds.forEach((seasonId) => {
  141. $.ajax('https://trophymanager.com/history/club/transfers/' + clubId + '/' + seasonId, {
  142. type: "GET",
  143. dataType: 'html',
  144. crossDomain: true,
  145. success: function (response) {
  146. let tbl = $('.zebra.hover', response);
  147. if (tbl.length != 2) {
  148. return;
  149. }
  150.  
  151. let trBuy = $('tr', tbl[0]);
  152. let playerId,
  153. playerName,
  154. price;
  155.  
  156. for (let i = 1; i < trBuy.length; i++) {
  157. let td = $('td', trBuy[i]);
  158. if (td.length < 4)
  159. continue;
  160. let a = $('a', td[0]);
  161. if (a.length == 0)
  162. continue;
  163.  
  164. playerName = a[0].innerText;
  165. playerId = a[0].getAttribute('player_link');
  166. price = td[3].innerText.replace(/,/g, '');
  167.  
  168. setMap(playerId, playerName, seasonId, price, 1);
  169. }
  170.  
  171. let trSell = $('tr', tbl[1]);
  172. for (let i = 1; i < trSell.length; i++) {
  173. let td = $('td', trSell[i]);
  174. if (td.length < 4)
  175. continue;
  176. let a = $('a', td[0]);
  177. if (a.length == 0)
  178. continue;
  179.  
  180. playerName = a[0].innerText;
  181. playerId = a[0].getAttribute('player_link');
  182. price = td[3].innerText.replace(/,/g, '');
  183.  
  184. setMap(playerId, playerName, seasonId, price, 2);
  185. }
  186.  
  187. let tdArr = $('.zebra.hover td', response);
  188. if (tdArr.length >= 3) {
  189. var bought,
  190. sold,
  191. balance,
  192. quantity,
  193. average;
  194.  
  195. bought = Math.round(tdArr[tdArr.length - 3].children[0].innerText.replace(/,/g, ''));
  196. sold = Math.round(tdArr[tdArr.length - 2].children[0].innerText.replace(/,/g, ''));
  197. balance = sold - bought;
  198. if (bought > 0 && sold > 0) {
  199. quantity = (tdArr.length - 3) / 4;
  200. } else if ((bought == 0 && sold > 0) || (bought > 0 && sold == 0)) {
  201. quantity = Math.round((tdArr.length - 4) / 4); //bug when has sell/buy players but all prices = 0 --> round and accept wrong result
  202. } else if (bought == 0 && sold == 0) {
  203. quantity = 0;
  204. }
  205. if (quantity == 0) {
  206. average = '0.0';
  207. } else {
  208. average = ((sold + bought) / quantity).toFixed(1);
  209. }
  210. transferSummary.push({
  211. Season: seasonId,
  212. Bought: bought,
  213. Sold: sold,
  214. Balance: balance,
  215. Quantity: quantity,
  216. Average: average
  217. });
  218. }
  219.  
  220. loadCount++;
  221. if (loadCount >= seasonIds.length) {
  222. loadDone = true;
  223. }
  224. },
  225. error: function (e) {}
  226. });
  227. });
  228. } else {
  229. loadDone = true;
  230. }
  231.  
  232. var myInterval = setInterval(append, 1000);
  233.  
  234. function append() {
  235. if (!loadDone) {
  236. return;
  237. }
  238. clearInterval(myInterval);
  239.  
  240. processPlayer();
  241. boughtArr.sort((a, b) => parseFloat(b.Price) - parseFloat(a.Price));
  242. soldArr.sort((a, b) => parseFloat(b.Price) - parseFloat(a.Price));
  243. tradeArr.sort((a, b) => parseFloat(b.Profit) - parseFloat(a.Profit));
  244.  
  245. transferSummary.sort(function (a, b) {
  246. return b.Season - a.Season
  247. }); //order an object array
  248. processAcademy();
  249.  
  250. present();
  251.  
  252. try {
  253. $('.banner_placeholder.rectangle')[0].parentNode.removeChild($('.banner_placeholder.rectangle')[0]);
  254. } catch (err) {}
  255. }
  256.  
  257. //buyOrSell: 1 - buy, 2 - sell
  258. function setMap(playerId, playerName, seasonId, price, buyOrSell) {
  259. let player;
  260. if (playerMap.has(playerId)) {
  261. player = playerMap.get(playerId);
  262. player.Transaction.push({
  263. SeasonBS: seasonId + '.' + buyOrSell,
  264. Price: price
  265. });
  266. try {
  267. if (player.Name.trim() == '') {
  268. player.Name = playerName; //fix bug of TM not show playername
  269. }
  270. } catch (e) {}
  271. } else {
  272. player = {
  273. Id: playerId,
  274. Name: playerName,
  275. Transaction: [{
  276. SeasonBS: seasonId + '.' + buyOrSell,
  277. Price: price
  278. }
  279. ]
  280. }
  281. playerMap.set(playerId, player);
  282. }
  283. }
  284.  
  285. function processPlayer() {
  286. totalTradeBuy = 0;
  287. totalTradeSell = 0;
  288. totalTradeProfit = 0;
  289. totalSquadBuy = 0;
  290. squadCount = 0;
  291. for (let[key, value]of playerMap) {
  292. value.Transaction.sort((a, b) => parseFloat(a.SeasonBS) - parseFloat(b.SeasonBS));
  293. let waitSellForTrade = false;
  294. let buyForTrade;
  295. value.Transaction.forEach(tran => {
  296. let temp = tran.SeasonBS.split('.');
  297. if (temp[1] == 1) {
  298. boughtArr.push({
  299. Id: value.Id,
  300. Name: value.Name,
  301. Season: temp[0],
  302. Price: tran.Price
  303. });
  304. waitSellForTrade = true;
  305. buyForTrade = tran.Price;
  306. } else {
  307. if (waitSellForTrade) {
  308. let afterTax = (tran.Price * 0.94).toFixed(1);
  309. let tradeProfit = Math.round((afterTax - buyForTrade) * 10) / 10;
  310. if (tradeProfit >= minProfit && tradeProfit <= maxProfit) {
  311. tradeArr.push({
  312. Id: value.Id,
  313. Name: value.Name,
  314. Buy: buyForTrade,
  315. Sell: afterTax,
  316. Profit: tradeProfit
  317. });
  318. totalTradeBuy += Math.round(parseFloat(buyForTrade) * 10) / 10;
  319. totalTradeSell += Math.round(parseFloat(afterTax) * 10) / 10;
  320. totalTradeProfit += Math.round(parseFloat(tradeProfit) * 10) / 10;
  321. }
  322. soldArr.push({
  323. Id: value.Id,
  324. Name: value.Name,
  325. Season: temp[0],
  326. Price: tran.Price,
  327. YoungAcademy: false
  328. });
  329. } else {
  330. soldArr.push({
  331. Id: value.Id,
  332. Name: value.Name,
  333. Season: temp[0],
  334. Price: tran.Price,
  335. YoungAcademy: true
  336. });
  337. if (academySoldMap.has(temp[0])) {
  338. let academySoldSeasonData = academySoldMap.get(temp[0]);
  339. academySoldSeasonData.Quantity++;
  340. academySoldSeasonData.Sold += Math.round(parseFloat(tran.Price) * 10) / 10;
  341. academySoldMap.set(temp[0], academySoldSeasonData);
  342. } else {
  343. academySoldMap.set(temp[0], {
  344. Quantity: 1,
  345. Sold: Math.round(parseFloat(tran.Price) * 10) / 10
  346. });
  347. }
  348. }
  349. waitSellForTrade = false;
  350. }
  351. });
  352. if (squadPlayerIdArr.includes(value.Id)) { //player is still playing in squad. Can not be inferred from transfer history data because bug data of TM
  353. totalSquadBuy += Math.round(parseFloat(buyForTrade) * 10) / 10;
  354. squadCount++;
  355. }
  356. }
  357. }
  358.  
  359. function processAcademy() {
  360. seasonIds.forEach((seasonId) => {
  361. if (academySoldMap.has(seasonId)) {
  362. let season = academySoldMap.get(seasonId);
  363.  
  364. let seasonAverage = (Math.round(season.Sold) / season.Quantity).toFixed(1);
  365. academySummary.push({
  366. Season: seasonId,
  367. Quantity: season.Quantity,
  368. Sold: Math.round(season.Sold),
  369. Average: seasonAverage
  370. });
  371. } else {
  372. academySummary.push({
  373. Season: seasonId,
  374. Quantity: 0,
  375. Sold: 0,
  376. Average: '0.0'
  377. });
  378. }
  379. });
  380. }
  381.  
  382. function present() {
  383. let clubTransfer =
  384. "<div class=\"box\">" +
  385. "<div class=\"box_head\">" +
  386. "<h2 class=\"std\">Club Transfer (M)</h2>" +
  387. "</div>" +
  388. "<div class=\"box_body\">" +
  389. "<div class=\"box_shadow\"></div>" +
  390. "<h3>TOP BOUGHT</h3>" +
  391. "<div id=\"topBought_content\" class=\"content_menu\"></div>" +
  392. "<h3>TOP SOLD</h3>" +
  393. "<div id=\"topSold_content\" class=\"content_menu\"></div>" +
  394. "<h3>TOP TRADE PROFIT (INCLUDE TAX)</h3>" +
  395. "<div id=\"topTrade_content\" class=\"content_menu\"></div>" +
  396. "<h3>SUMMARY TRANSFER</h3>" +
  397. "<div id=\"summaryTransfer_content\" class=\"content_menu\"></div>" +
  398. "<h3>ACADEMY REVENUE</h3>" +
  399. "<div id=\"academyRevenue_content\" class=\"content_menu\"></div>" +
  400. "<h3>CONFIG</h3>" +
  401. "<table>" +
  402. "<tr>" +
  403. "<td>" +
  404. "<span style='display: inline-block;'><input id='" + CONTROL_ID.INPUT_SHOW_MODE + "' type='text' class='embossed' style='width: 150px; line-height: 100%; padding: 3px 3px 4px 3px;' placeholder='Mode'></span>" +
  405. "</td>" +
  406. "<td>" +
  407. "<span id='" + CONTROL_ID.BUTTON_SHOW_MODE + "' class='button' style='margin-left: 3px;'><span class='button_border'>Show Mode</span></span>" +
  408. "</td>" +
  409. "</tr>" +
  410. "<tr>" +
  411. "<td>" +
  412. "<span style='display: inline-block;'><input id='" + CONTROL_ID.INPUT_TOP_COUNT + "' type='text' class='embossed' style='width: 150px; line-height: 100%; padding: 3px 3px 4px 3px;' placeholder='Top count'></span>" +
  413. "</td>" +
  414. "<td>" +
  415. "<span id='" + CONTROL_ID.BUTTON_TOP_COUNT + "' class='button' style='margin-left: 3px;'><span class='button_border'>Top Count</span></span>" +
  416. "</td>" +
  417. "</tr>" +
  418. "<tr>" +
  419. "<td>" +
  420. "<span style='display: inline-block;'><input id='" + CONTROL_ID.INPUT_SEASON_COUNT + "' type='text' class='embossed' style='width: 65px; line-height: 100%; padding: 3px 3px 4px 3px;' placeholder='Count'></span>" +
  421. " - " +
  422. "<span style='display: inline-block;'><input id='" + CONTROL_ID.INPUT_TO_SEASON + "' type='text' class='embossed' style='width: 65px; line-height: 100%; padding: 3px 3px 4px 3px;' placeholder='To season'></span>" +
  423. "</td>" +
  424. "<td>" +
  425. "<span id='" + CONTROL_ID.BUTTON_SEASON_COUNT + "' class='button' style='margin-left: 3px;'><span class='button_border'>Season Count</span></span>" +
  426. "</td>" +
  427. "</tr>" +
  428. "<tr>" +
  429. "<td>" +
  430. "<span style='display: inline-block;'><input id='" + CONTROL_ID.INPUT_MIN_PROFIT + "' type='text' class='embossed' style='width: 65px; line-height: 100%; padding: 3px 3px 4px 3px;' placeholder='Min profit'></span>" +
  431. " - " +
  432. "<span style='display: inline-block;'><input id='" + CONTROL_ID.INPUT_MAX_PROFIT + "' type='text' class='embossed' style='width: 65px; line-height: 100%; padding: 3px 3px 4px 3px;' placeholder='Max profit'></span>" +
  433. "</td>" +
  434. "<td>" +
  435. "<span id='" + CONTROL_ID.BUTTON_TRADE_PROFIT + "' class='button' style='margin-left: 3px;'><span class='button_border'>Profit (M)</span></span>" +
  436. "</td>" +
  437. "</tr>" +
  438. "</table>" +
  439. "</div>" +
  440. "<div class=\"box_footer\">" +
  441. "<div></div>" +
  442. "</div>" +
  443. "</div>";
  444. $(".column3_a").append(clubTransfer);
  445.  
  446. /*** SHOW MODE ***/
  447. document.getElementById(CONTROL_ID.BUTTON_SHOW_MODE).addEventListener('click', (e) => {
  448. setShowMode();
  449. });
  450. let showMode = localStorage.getItem(APPLICATION_PARAM.SHOW_MODE_LOCAL_STORAGE_KEY);
  451. if (showMode == null || showMode == "") {
  452. showMode = APPLICATION_PARAM.DEFAULT_SHOW_MODE;
  453. }
  454. $('#' + CONTROL_ID.INPUT_SHOW_MODE).val(showMode);
  455. /*********/
  456.  
  457. /*** TOP COUT ***/
  458. document.getElementById(CONTROL_ID.BUTTON_TOP_COUNT).addEventListener('click', (e) => {
  459. setTopCount();
  460. });
  461. topCount = localStorage.getItem(APPLICATION_PARAM.TOP_COUNT_LOCAL_STORAGE_KEY);
  462. if (topCount == null || topCount == "") {
  463. topCount = APPLICATION_PARAM.DEFAULT_TOP_COUNT;
  464. }
  465. $('#' + CONTROL_ID.INPUT_TOP_COUNT).val(topCount);
  466. /*********/
  467.  
  468. /*** SEASON COUT ***/
  469. document.getElementById(CONTROL_ID.BUTTON_SEASON_COUNT).addEventListener('click', (e) => {
  470. setSeasonCount();
  471. });
  472. $('#' + CONTROL_ID.INPUT_SEASON_COUNT).val(seasonCount);
  473. $('#' + CONTROL_ID.INPUT_TO_SEASON).val(toSeason);
  474. /*********/
  475.  
  476. /*** MIN PROFIT ***/
  477. document.getElementById(CONTROL_ID.BUTTON_TRADE_PROFIT).addEventListener('click', (e) => {
  478. setTradeProfit();
  479. });
  480. $('#' + CONTROL_ID.INPUT_MIN_PROFIT).val(minProfit);
  481. $('#' + CONTROL_ID.INPUT_MAX_PROFIT).val(maxProfit);
  482. /*********/
  483.  
  484. let invidualMode = showMode.split("");
  485. if (invidualMode[0] == "1") {
  486. showTopBought();
  487. }
  488. if (invidualMode[1] == "1") {
  489. showTopSold();
  490. }
  491. if (invidualMode[2] == "1") {
  492. showTopTradeProfit();
  493. }
  494. if (invidualMode[3] == "1") {
  495. showSummaryTransfer();
  496. }
  497. if (invidualMode[4] == "1") {
  498. showAcademyRevenue();
  499. }
  500. }
  501.  
  502. function showTopBought() {
  503. if (boughtArr.length > 0) {
  504. var topBought_content = "<table>" +
  505. "<tr style='color:Orange;'><th align='right'>#</th><th>Player</th><th align='right'>SS</th><th align='right'>Price</th></tr>";
  506. let rowCount = 0;
  507. for (let i = 0; i < boughtArr.length && i < topCount; i++) {
  508. rowCount++;
  509. let classOdd = "";
  510. if ((rowCount % 2) == 1) {
  511. classOdd = "class='odd'";
  512. }
  513. topBought_content +=
  514. '<tr ' + classOdd + '><td align="right">' + (i + 1) + '. ' +
  515. '</td><td>' + '<span onclick = \"window.open(\'https:\/\/trophymanager.com\/players\/' + boughtArr[i].Id + '\')\">' + boughtArr[i].Name + '</span>' +
  516. '</td><td align="right">' + boughtArr[i].Season +
  517. '</td><td align="right">' + boughtArr[i].Price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
  518. '</td></tr>';
  519. }
  520. topBought_content += "</table>";
  521. $("#topBought_content").append(topBought_content);
  522. }
  523. }
  524.  
  525. function showTopSold() {
  526. if (soldArr.length > 0) {
  527. var topSold_content = "<table>" +
  528. "<tr style='color:Orange;'><th align='right'>#</th><th>Player</th><th align='right'>SS</th><th align='right'>Price</th></tr>";
  529. let rowCount = 0;
  530. for (let i = 0; i < soldArr.length && i < topCount; i++) {
  531. rowCount++;
  532. let classOdd = "";
  533. if ((rowCount % 2) == 1) {
  534. classOdd = "class='odd'";
  535. }
  536. if (soldArr[i].YoungAcademy && seasonCount == APPLICATION_PARAM.DEFAULT_SEASON_COUNT) {
  537. topSold_content += "<tr style='color:Yellow;' " + classOdd + ">";
  538. } else {
  539. topSold_content += "<tr " + classOdd + ">";
  540. }
  541. topSold_content +=
  542. '<td align="right">' + (i + 1) + '. ' +
  543. '</td><td>' + '<span onclick = \"window.open(\'https:\/\/trophymanager.com\/players\/' + soldArr[i].Id + '\')\">' + soldArr[i].Name + '</span>' +
  544. '</td><td align="right">' + soldArr[i].Season +
  545. '</td><td align="right">' + soldArr[i].Price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
  546. '</td></tr>';
  547. }
  548. topSold_content += "</table>";
  549. $("#topSold_content").append(topSold_content);
  550. }
  551. }
  552.  
  553. function showTopTradeProfit() {
  554. if (tradeArr.length > 0) {
  555. var topTrade_content = "<table>" +
  556. "<tr style='color:Orange;'><th align='right'>#</th><th>Player</th><th align='right'>Buy</th><th align='right'>Sell</th><th align='right'>Profit</th></tr>";
  557.  
  558. topTrade_content +=
  559. '<tr class="odd" style="color:' + APPLICATION_COLOR.AVERAGE + ';"><td></td><td>Average (' + tradeArr.length + ' players)</td><td align="right">' +
  560. (totalTradeBuy / tradeArr.length).toFixed(1).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' +
  561. (totalTradeSell / tradeArr.length).toFixed(1).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' +
  562. (totalTradeProfit / tradeArr.length).toFixed(1).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td></tr>';
  563.  
  564. topTrade_content +=
  565. '<tr style="color:' + APPLICATION_COLOR.TOTAL + ';"><td></td><td>Total (' + tradeArr.length + ' players)</td><td align="right">' +
  566. totalTradeBuy.toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' +
  567. totalTradeSell.toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' +
  568. totalTradeProfit.toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td></tr>';
  569.  
  570. let rowCount = 0;
  571. for (let i = 0; i < tradeArr.length && i < topCount; i++) {
  572. rowCount++;
  573. let classOdd = "";
  574. if ((rowCount % 2) == 1) {
  575. classOdd = "class='odd'";
  576. }
  577. topTrade_content +=
  578. '<tr ' + classOdd + '><td align="right">' + (i + 1) + '. ' +
  579. '</td><td>' + '<span onclick = \"window.open(\'https:\/\/trophymanager.com\/players\/' + tradeArr[i].Id + '\')\">' + tradeArr[i].Name + '</span>' +
  580. '</td><td align="right">' + tradeArr[i].Buy.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
  581. '</td><td align="right" style="color:Orange;">' + tradeArr[i].Sell.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
  582. '</td><td align="right">' + tradeArr[i].Profit.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
  583. '</td></tr>';
  584. }
  585. topTrade_content += "</table>";
  586. $("#topTrade_content").append(topTrade_content);
  587. }
  588. }
  589.  
  590. function showSummaryTransfer() {
  591. let summaryTransfer_content = "<table>" +
  592. "<tr style='color:Orange;'><th align='right'>SS</th><th align='right'>Buy</th><th align='right'>Sell</th><th align='right'>+-</th><th align='right'>#</th><th align='right'>Avg</th></tr>";
  593.  
  594. let totalBought = 0,
  595. totalSold = 0,
  596. totalQuantity = 0;
  597. let rowCount = 0;
  598. let seasonTrArr = [];
  599. transferSummary.forEach((summary) => {
  600. rowCount++;
  601. let trClass = "",
  602. display = "";
  603. if (rowCount <= APPLICATION_PARAM.SEASON_SHOW) {
  604. if ((rowCount % 2) == 0) {
  605. trClass = "class='odd'";
  606. }
  607. } else {
  608. display = "style='display:none'";
  609. if ((rowCount % 2) == 0) {
  610. trClass = "class='odd " + CLASS_NAME.SUMMARY_TRANSFER + "'";
  611. } else {
  612. trClass = "class='" + CLASS_NAME.SUMMARY_TRANSFER + "'";
  613. }
  614. }
  615.  
  616. let seasonTr =
  617. '<tr ' + trClass + ' ' + display + '><td align="right">' + summary.Season +
  618. '</td><td align="right">' + summary.Bought.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
  619. '</td><td align="right">' + summary.Sold.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
  620. '</td><td align="right">' + summary.Balance.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
  621. '</td><td align="right">' + summary.Quantity +
  622. '</td><td align="right">' + summary.Average.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
  623. '</td></tr>';
  624. seasonTrArr.push(seasonTr);
  625.  
  626. totalBought += summary.Bought;
  627. totalSold += summary.Sold;
  628. totalQuantity += summary.Quantity;
  629. });
  630.  
  631. summaryTransfer_content +=
  632. '<tr class="odd" style="color:' + APPLICATION_COLOR.AVERAGE + ';"><td align="right">Average</td><td align="right">' +
  633. (totalBought / transferSummary.length).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' +
  634. (totalSold / transferSummary.length).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' +
  635. (Math.round(totalSold / transferSummary.length) - Math.round(totalBought / transferSummary.length)).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' +
  636. (totalQuantity / transferSummary.length).toFixed(0) + '</td><td align="right">' +
  637. (totalQuantity > 0 ? ((totalSold + totalBought) / totalQuantity).toFixed(1).replace(/\B(?=(\d{3})+(?!\d))/g, ",") : 0) + '</td></tr>';
  638.  
  639. summaryTransfer_content +=
  640. '<tr style="color:' + APPLICATION_COLOR.TOTAL + ';"><td align="right">Total</td><td align="right">' +
  641. totalBought.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' +
  642. totalSold.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' +
  643. (totalSold - totalBought).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' +
  644. totalQuantity.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' +
  645. '</td></tr>';
  646.  
  647. if (seasonCount == APPLICATION_PARAM.DEFAULT_SEASON_COUNT) { //only display onSquadTotalBuy if show all seasons
  648. summaryTransfer_content +=
  649. '<tr class="odd" style="color:' + APPLICATION_COLOR.ONSQUAD + ';"><td align="right">Squad (' + squadCount + ')</td><td align="right">' +
  650. totalSquadBuy.toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right"></td><td align="right">' +
  651. (totalSquadBuy + totalSold - totalBought).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right"></td><td align="right">' +
  652. '</td></tr>';
  653. } else {
  654. summaryTransfer_content +=
  655. '<tr class="odd" style="color:' + APPLICATION_COLOR.ONSQUAD + ';"><td align="right">Squad</td><td align="right" colspan="5">Show if summary all seasons</td></tr>';
  656. }
  657.  
  658. seasonTrArr.forEach((seasonTr) => {
  659. summaryTransfer_content += seasonTr;
  660. });
  661. if (rowCount > APPLICATION_PARAM.SEASON_SHOW) {
  662. let buttonLabel = "Show all season " + seasonIds[seasonIds.length - 1] + " - " + seasonIds[0];
  663. summaryTransfer_content += "<tr align='center'><td colspan='6'>" + "<span id='" + CONTROL_ID.BUTTON_SHOW_ALL_SUMMARY_TRANSFER + "' class='button' style='margin-left: 3px;'><span class='button_border'>" + buttonLabel + "</span></span>" + "</td></tr>";
  664. }
  665. summaryTransfer_content += "</table>";
  666. $("#summaryTransfer_content").append(summaryTransfer_content);
  667.  
  668. if (rowCount > APPLICATION_PARAM.SEASON_SHOW) {
  669. document.getElementById(CONTROL_ID.BUTTON_SHOW_ALL_SUMMARY_TRANSFER).addEventListener('click', (e) => {
  670. showAll(CLASS_NAME.SUMMARY_TRANSFER, CONTROL_ID.BUTTON_SHOW_ALL_SUMMARY_TRANSFER);
  671. });
  672. }
  673. }
  674.  
  675. function showAcademyRevenue() {
  676. let academyRevenue_content = "<table>" +
  677. "<tr style='color:Orange;'><th align='right'>SS</th><th align='right'>Sell</th><th align='right'>#</th><th align='right'>Avg</th></tr>";
  678.  
  679. let totalSold = 0,
  680. totalQuantity = 0;
  681. let rowCount = 0;
  682. let seasonTrArr = [];
  683. academySummary.forEach((summary) => {
  684. rowCount++;
  685. let trClass = "",
  686. display = "";
  687. if (rowCount <= APPLICATION_PARAM.SEASON_SHOW) {
  688. if ((rowCount % 2) == 1) {
  689. trClass = "class='odd'";
  690. }
  691. } else {
  692. display = "style='display:none'";
  693. if ((rowCount % 2) == 1) {
  694. trClass = "class='odd " + CLASS_NAME.ACADEMY_REVENUE + "'";
  695. } else {
  696. trClass = "class='" + CLASS_NAME.ACADEMY_REVENUE + "'";
  697. }
  698. }
  699.  
  700. let seasonTr =
  701. '<tr ' + trClass + ' ' + display + '><td align="right">' + summary.Season +
  702. '</td><td align="right">' + summary.Sold.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
  703. '</td><td align="right">' + summary.Quantity +
  704. '</td><td align="right">' + summary.Average.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
  705. '</td></tr>';
  706. seasonTrArr.push(seasonTr);
  707.  
  708. totalSold += summary.Sold;
  709. totalQuantity += summary.Quantity;
  710. });
  711.  
  712. academyRevenue_content +=
  713. '<tr class="odd" style="color:' + APPLICATION_COLOR.AVERAGE + ';"><td align="right">Average</td><td align="right">' +
  714. (totalSold / academySummary.length).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' +
  715. (totalQuantity / academySummary.length).toFixed(0) + '</td><td align="right">' +
  716. (totalQuantity > 0 ? (totalSold / totalQuantity).toFixed(1).replace(/\B(?=(\d{3})+(?!\d))/g, ",") : 0) + '</td></tr>';
  717.  
  718. academyRevenue_content +=
  719. '<tr style="color:' + APPLICATION_COLOR.TOTAL + ';"><td align="right">Total</td><td align="right">' +
  720. totalSold.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' +
  721. totalQuantity.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' +
  722. '</td></tr>';
  723.  
  724. seasonTrArr.forEach((seasonTr) => {
  725. academyRevenue_content += seasonTr;
  726. });
  727. if (rowCount > APPLICATION_PARAM.SEASON_SHOW) {
  728. let buttonLabel = "Show all season " + seasonIds[seasonIds.length - 1] + " - " + seasonIds[0];
  729. academyRevenue_content += "<tr align='center'><td colspan='4'>" + "<span id='" + CONTROL_ID.BUTTON_SHOW_ALL_ACADEMY_REVENUE + "' class='button' style='margin-left: 3px;'><span class='button_border'>" + buttonLabel + "</span></span>" + "</td></tr>";
  730. }
  731. academyRevenue_content += "</table>";
  732. $("#academyRevenue_content").append(academyRevenue_content);
  733.  
  734. if (rowCount > APPLICATION_PARAM.SEASON_SHOW) {
  735. document.getElementById(CONTROL_ID.BUTTON_SHOW_ALL_ACADEMY_REVENUE).addEventListener('click', (e) => {
  736. showAll(CLASS_NAME.ACADEMY_REVENUE, CONTROL_ID.BUTTON_SHOW_ALL_ACADEMY_REVENUE);
  737. });
  738. }
  739. }
  740.  
  741. function showAll(className, controlId) {
  742. let trArr = $('.' + className);
  743. for (let i = 0; i < trArr.length; i++) {
  744. trArr[i].style = 'display:""';
  745. }
  746. $('#' + controlId)[0].style = 'display:none';
  747. }
  748.  
  749. function setShowMode() {
  750. let showMode = $('#' + CONTROL_ID.INPUT_SHOW_MODE)[0].value;
  751. if (showMode == '') {
  752. localStorage.removeItem(APPLICATION_PARAM.SHOW_MODE_LOCAL_STORAGE_KEY);
  753. } else if (!isValidShowMode(showMode)) {
  754. alert('Allowable show mode value has the form XXXXX where X is 0 or 1');
  755. } else {
  756. localStorage.setItem(APPLICATION_PARAM.SHOW_MODE_LOCAL_STORAGE_KEY, showMode);
  757. alert('Set successful, please refresh');
  758. }
  759. }
  760.  
  761. function isValidShowMode(mode) {
  762. let arr = mode.split('');
  763. if (arr.length != 5)
  764. return false;
  765. for (let i = 0; i < arr.length; i++) {
  766. if (arr[i] != '0' && arr[i] != '1') {
  767. return false;
  768. }
  769. }
  770. return true;
  771. }
  772.  
  773. function setTopCount() {
  774. let topCount = $('#' + CONTROL_ID.INPUT_TOP_COUNT)[0].value;
  775. if (topCount == '') {
  776. localStorage.removeItem(APPLICATION_PARAM.TOP_COUNT_LOCAL_STORAGE_KEY);
  777. } else if (isNaN(topCount) || topCount <= 0) {
  778. alert('Top count must be positive integer');
  779. } else {
  780. localStorage.setItem(APPLICATION_PARAM.TOP_COUNT_LOCAL_STORAGE_KEY, topCount);
  781. alert('Set successful, please refresh');
  782. }
  783. }
  784.  
  785. function setSeasonCount() {
  786. let seasonCount = $('#' + CONTROL_ID.INPUT_SEASON_COUNT)[0].value;
  787. let toSeason = $('#' + CONTROL_ID.INPUT_TO_SEASON)[0].value;
  788. let valid = true;
  789. if (seasonCount == '') {
  790. localStorage.removeItem(APPLICATION_PARAM.SEASON_COUNT_LOCAL_STORAGE_KEY);
  791. } else if (isNaN(seasonCount) || seasonCount < 0) {
  792. alert('Season count must be positive integer. Season count = 0 means all seasons.');
  793. valid = false;
  794. } else {
  795. localStorage.setItem(APPLICATION_PARAM.SEASON_COUNT_LOCAL_STORAGE_KEY, seasonCount);
  796. }
  797. if (toSeason == '') {
  798. localStorage.removeItem(APPLICATION_PARAM.TO_SEASON_LOCAL_STORAGE_KEY);
  799. } else if (isNaN(toSeason) || toSeason < 0) {
  800. alert('To season must be positive integer. To season = 0 means current season.');
  801. valid = false;
  802. } else {
  803. localStorage.setItem(APPLICATION_PARAM.TO_SEASON_LOCAL_STORAGE_KEY, toSeason);
  804. }
  805. if (valid) {
  806. alert('Set successful, please refresh');
  807. }
  808. }
  809.  
  810. function setTradeProfit() {
  811. let minProfit = $('#' + CONTROL_ID.INPUT_MIN_PROFIT)[0].value;
  812. let maxProfit = $('#' + CONTROL_ID.INPUT_MAX_PROFIT)[0].value;
  813. let valid = true;
  814. if (minProfit == '') {
  815. localStorage.removeItem(APPLICATION_PARAM.MIN_PROFIT_LOCAL_STORAGE_KEY);
  816. } else if (isNaN(minProfit)) {
  817. alert('Min profit must be number');
  818. valid = false;
  819. } else {
  820. localStorage.setItem(APPLICATION_PARAM.MIN_PROFIT_LOCAL_STORAGE_KEY, minProfit);
  821. }
  822. if (maxProfit == '') {
  823. localStorage.removeItem(APPLICATION_PARAM.MAX_PROFIT_LOCAL_STORAGE_KEY);
  824. } else if (isNaN(maxProfit)) {
  825. alert('Max profit must be number');
  826. valid = false;
  827. } else {
  828. localStorage.setItem(APPLICATION_PARAM.MAX_PROFIT_LOCAL_STORAGE_KEY, maxProfit);
  829. }
  830. if (valid) {
  831. alert('Set successful, please refresh');
  832. }
  833. }
  834. })();

QingJ © 2025

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