您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
Trophymanager: transfer statistics of all seasons, the most expensive players, the most successful trades, revenue from the academy... A gift for Vasco Vitkovice and Tirana Smokers. In addition, the script also saves data for for TMVN League Transfer script (http://greasyfork.icu/en/scripts/416755).
当前为
// ==UserScript== // @name TMVN Club Transfer // @namespace https://trophymanager.com // @version 5 // @description Trophymanager: transfer statistics of all seasons, the most expensive players, the most successful trades, revenue from the academy... A gift for Vasco Vitkovice and Tirana Smokers. In addition, the script also saves data for for TMVN League Transfer script (http://greasyfork.icu/en/scripts/416755). // @include https://trophymanager.com/club/* // @include https://trophymanager.com/club/*/ // @exclude https://trophymanager.com/club/ // @exclude https://trophymanager.com/club/*/squad/ // @grant none // ==/UserScript== (function () { 'use strict'; const APPLICATION_PARAM = { DEFAULT_TOP_COUNT: 10, LOCAL_STORAGE_KEY: "TMVN_TRADE_STATISTIC_TOP_COUNT" } var boughtArr = []; var soldArr = []; var tradeArr = []; var academySoldMap = new Map(); var academySummary = []; var transferSummary = []; var playerMap = new Map(); var loadCount = 0; var loadDone = false; var clubId = location.href.split('/')[4]; var seasonIds = []; $.ajaxSetup({ async: false }); $.ajax('https://trophymanager.com/history/club/transfers/' + clubId, { type: "GET", dataType: 'html', crossDomain: true, success: function (response) { let comboSeason = $('#stats_season', response)[0].options; for (let i = 0; i < comboSeason.length; i++) { seasonIds.push(comboSeason[i].value); } }, error: function (e) {} }); $.ajaxSetup({ async: true }); if (clubId != "" && seasonIds.length > 0) { seasonIds.forEach((seasonId) => { $.ajax('https://trophymanager.com/history/club/transfers/' + clubId + '/' + seasonId, { type: "GET", dataType: 'html', crossDomain: true, success: function (response) { let tbl = $('.zebra.hover', response); if (tbl.length != 2) { return; } let trBuy = $('tr', tbl[0]); let playerId, playerName, price; for (let i = 1; i < trBuy.length; i++) { let td = $('td', trBuy[i]); if (td.length < 4) continue; let a = $('a', td[0]); if (a.length == 0) continue; playerName = a[0].innerText; playerId = a[0].getAttribute('player_link'); price = td[3].innerText.replace(/,/g, ''); setMap(playerId, playerName, seasonId, price, 1); } let trSell = $('tr', tbl[1]); for (let i = 1; i < trSell.length; i++) { let td = $('td', trSell[i]); if (td.length < 4) continue; let a = $('a', td[0]); if (a.length == 0) continue; playerName = a[0].innerText; playerId = a[0].getAttribute('player_link'); price = td[3].innerText.replace(/,/g, ''); setMap(playerId, playerName, seasonId, price, 2); } let tdArr = $('.zebra.hover td', response); if (tdArr.length >= 3) { var bought, sold, balance, quantity, average; bought = Math.round(tdArr[tdArr.length - 3].children[0].innerText.replace(/,/g, '')); sold = Math.round(tdArr[tdArr.length - 2].children[0].innerText.replace(/,/g, '')); balance = sold - bought; if (bought > 0 && sold > 0) { quantity = (tdArr.length - 3) / 4; } else if ((bought == 0 && sold > 0) || (bought > 0 && sold == 0)) { quantity = Math.round((tdArr.length - 4) / 4); //bug when has sell/buy players but all prices = 0 --> round and accept wrong result } else if (bought == 0 && sold == 0) { quantity = 0; } if (quantity == 0) { average = '0.0'; } else { average = ((sold + bought) / quantity).toFixed(1); } transferSummary.push({ Season: seasonId, Bought: bought, Sold: sold, Balance: balance, Quantity: quantity, Average: average }); } loadCount++; if (loadCount >= seasonIds.length) { loadDone = true; } }, error: function (e) {} }); }); } var myInterval = setInterval(append, 1000); function append() { if (!loadDone) { return; } clearInterval(myInterval); processPlayer(); boughtArr.sort((a, b) => parseFloat(b.Price) - parseFloat(a.Price)); soldArr.sort((a, b) => parseFloat(b.Price) - parseFloat(a.Price)); tradeArr.sort((a, b) => parseFloat(b.Profit) - parseFloat(a.Profit)); transferSummary.sort(function (a, b) { return b.Season - a.Season }); //order an object array processAcademy(); if (!(boughtArr.length == 0 && soldArr.length == 0 && tradeArr.length == 0)) { presentTransferStatistic(); presentTransferSummary(); presentAcademySummary(); } try { $('.banner_placeholder.rectangle')[0].parentNode.removeChild($('.banner_placeholder.rectangle')[0]); } catch (err) {} } //buyOrSell: 1 - buy, 2 - sell function setMap(playerId, playerName, seasonId, price, buyOrSell) { let player; if (playerMap.has(playerId)) { player = playerMap.get(playerId); player.Transaction.push({ SeasonBS: seasonId + '.' + buyOrSell, Price: price }); } else { player = { Id: playerId, Name: playerName, Transaction: [{ SeasonBS: seasonId + '.' + buyOrSell, Price: price } ] } playerMap.set(playerId, player); } } function processPlayer() { for (let[key, value]of playerMap) { value.Transaction.sort((a, b) => parseFloat(a.SeasonBS) - parseFloat(b.SeasonBS)); let waitSellForTrade = false; let buyForTrade; value.Transaction.forEach(tran => { let temp = tran.SeasonBS.split('.'); if (temp[1] == 1) { boughtArr.push({ Id: value.Id, Name: value.Name, Season: temp[0], Price: tran.Price }); waitSellForTrade = true; buyForTrade = tran.Price; } else { if (waitSellForTrade) { tradeArr.push({ Id: value.Id, Name: value.Name, Buy: buyForTrade, Sell: tran.Price, Profit: (tran.Price - buyForTrade).toFixed(1) }); soldArr.push({ Id: value.Id, Name: value.Name, Season: temp[0], Price: tran.Price, YoungAcademy: false }); } else { soldArr.push({ Id: value.Id, Name: value.Name, Season: temp[0], Price: tran.Price, YoungAcademy: true }); if (academySoldMap.has(temp[0])) { let academySoldSeasonData = academySoldMap.get(temp[0]); academySoldSeasonData.Quantity++; academySoldSeasonData.Sold += parseFloat(tran.Price); academySoldMap.set(temp[0], academySoldSeasonData); } else { academySoldMap.set(temp[0], { Quantity: 1, Sold: parseFloat(tran.Price) }); } } waitSellForTrade = false; } }); } } function processAcademy() { seasonIds.forEach((seasonId) => { if (academySoldMap.has(seasonId)) { let season = academySoldMap.get(seasonId); let seasonAverage = (Math.round(season.Sold) / season.Quantity).toFixed(1); academySummary.push({ Season: seasonId, Quantity: season.Quantity, Sold: Math.round(season.Sold), Average: seasonAverage }); } else { academySummary.push({ Season: seasonId, Quantity: 0, Sold: 0, Average: '0.0' }); } }); } function presentTransferSummary() { var summaryTransfer = "<div class=\"box\">" + "<div class=\"box_head\">" + "<h2 class=\"std\">Summary Transfer (M)</h2>" + "</div>" + "<div class=\"box_body\">" + "<div class=\"box_shadow\"></div>" + "<div id=\"summaryTransfer_content\" class=\"content_menu\"></div>" + "</div>" + "<div class=\"box_footer\">" + "<div></div>" + "</div>" + "</div>"; $(".column3_a").append(summaryTransfer); var summaryTransfer_content = "<table>" + "<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>"; var totalBought = 0, totalSold = 0, totalQuantity = 0; transferSummary.forEach((summary) => { summaryTransfer_content += '<tr><td align="right">' + summary.Season + '</td><td align="right">' + summary.Bought.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + summary.Sold.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + summary.Balance.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + summary.Quantity + '</td><td align="right">' + summary.Average.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td></tr>'; totalBought += summary.Bought; totalSold += summary.Sold; totalQuantity += summary.Quantity; }); summaryTransfer_content += '<tr><td align="right"><span style="color:Orange;">Average</span></td><td align="right">' + (totalBought / transferSummary.length).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + (totalSold / transferSummary.length).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + (Math.round(totalSold / transferSummary.length) - Math.round(totalBought / transferSummary.length)).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + (totalQuantity / transferSummary.length).toFixed(0) + '</td><td align="right">' + (totalQuantity > 0 ? ((totalSold + totalBought) / totalQuantity).toFixed(1).replace(/\B(?=(\d{3})+(?!\d))/g, ",") : 0) + '</td></tr>'; summaryTransfer_content += '<tr><td align="right"><span style="color:Orange;">Total</span></td><td align="right">' + totalBought.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + totalSold.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + (totalSold - totalBought).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + totalQuantity.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + '</td></tr>'; summaryTransfer_content += "</table>"; $("#summaryTransfer_content").append(summaryTransfer_content); localStorage.setItem(clubId + "_AVERAGE_TRANSFER", JSON.stringify({ "Time": new Date(), "Bought": Number((totalBought / transferSummary.length).toFixed(0)), "Sold": Number((totalSold / transferSummary.length).toFixed(0)), "Balance": Math.round(totalSold / transferSummary.length) - Math.round(totalBought / transferSummary.length), "Quantity": Number((totalQuantity / transferSummary.length).toFixed(0)), "Average": totalQuantity > 0 ? Number(((totalSold + totalBought) / totalQuantity).toFixed(1)) : 0, "SeasonCount": transferSummary.length })); } function presentAcademySummary() { var academyTransfer = "<div class=\"box\">" + "<div class=\"box_head\">" + "<h2 class=\"std\">Academy Transfer (M)</h2>" + "</div>" + "<div class=\"box_body\">" + "<div class=\"box_shadow\"></div>" + "<div id=\"academyTransfer_content\" class=\"content_menu\"></div>" + "</div>" + "<div class=\"box_footer\">" + "<div></div>" + "</div>" + "</div>"; $(".column3_a").append(academyTransfer); var academyTransfer_content = "<table>" + "<tr style='color:Orange;'><th align='right'>SS</th><th align='right'>Sold</th><th align='right'>#</th><th align='right'>Avg</th></tr>"; var totalSold = 0, totalQuantity = 0; academySummary.forEach((summary) => { academyTransfer_content += '<tr><td align="right">' + summary.Season + '</td><td align="right">' + summary.Sold.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + summary.Quantity + '</td><td align="right">' + summary.Average.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td></tr>'; totalSold += summary.Sold; totalQuantity += summary.Quantity; }); academyTransfer_content += '<tr><td align="right"><span style="color:Orange;">Average</span></td><td align="right">' + (totalSold / academySummary.length).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + (totalQuantity / academySummary.length).toFixed(0) + '</td><td align="right">' + (totalQuantity > 0 ? (totalSold / totalQuantity).toFixed(1).replace(/\B(?=(\d{3})+(?!\d))/g, ",") : 0) + '</td></tr>'; academyTransfer_content += '<tr><td align="right"><span style="color:Orange;">Total</span></td><td align="right">' + totalSold.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + totalQuantity.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + '</td></tr>'; academyTransfer_content += "</table>"; $("#academyTransfer_content").append(academyTransfer_content); } function presentTransferStatistic() { var tradeStatistic = "<div class=\"box\">" + "<div class=\"box_head\">" + "<h2 class=\"std\">Trade Statistic (M)</h2>" + "</div>" + "<div class=\"box_body\">" + "<div class=\"box_shadow\"></div>" + "<span style='display: inline-block;'><input id='tm_script_input_top_number' type='text' class='embossed' style='min-width: 100px; line-height: 100%; padding: 3px 3px 4px 3px;' placeholder='Top count'></span>" + "<span id='tm_script_button_top_set' class='button' style='margin-left: 3px;'><span class='button_border'>Set top count</span></span>" + "<h3>TOP BOUGHT</h3>" + "<div id=\"topBought_content\" class=\"content_menu\"></div>" + "<h3>TOP SOLD</h3>" + "<div id=\"topSold_content\" class=\"content_menu\"></div>" + "<h3>TOP TRADE PROFIT</h3>" + "<div id=\"topTrade_content\" class=\"content_menu\"></div>" + "</div>" + "<div class=\"box_footer\">" + "<div></div>" + "</div>" + "</div>"; $(".column3_a").append(tradeStatistic); document.getElementById('tm_script_button_top_set').addEventListener('click', (e) => { setTopCount(); }); let topCount = localStorage.getItem(APPLICATION_PARAM.LOCAL_STORAGE_KEY); if (topCount == null || topCount == "") { topCount = APPLICATION_PARAM.DEFAULT_TOP_COUNT; } $('#tm_script_input_top_number').val(topCount); if (boughtArr.length > 0) { var topBought_content = "<table>" + "<tr style='color:Orange;'><th align='right'>#</th><th>Player</th><th align='right'>SS</th><th align='right'>Price</th></tr>"; for (let i = 0; i < boughtArr.length && i < topCount; i++) { topBought_content += '<tr><td align="right">' + (i + 1) + '. ' + '</td><td>' + '<span onclick = \"window.open(\'https:\/\/trophymanager.com\/players\/' + boughtArr[i].Id + '\')\">' + boughtArr[i].Name + '</span>' + '</td><td align="right">' + boughtArr[i].Season + '</td><td align="right">' + boughtArr[i].Price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td></tr>'; } topBought_content += "</table>"; $("#topBought_content").append(topBought_content); } if (soldArr.length > 0) { var topSold_content = "<table>" + "<tr style='color:Orange;'><th align='right'>#</th><th>Player</th><th align='right'>SS</th><th align='right'>Price</th></tr>"; for (let i = 0; i < soldArr.length && i < topCount; i++) { if (soldArr[i].YoungAcademy) { topSold_content += "<tr style='color:Yellow;'>"; } else { topSold_content += "<tr>"; } topSold_content += '<td align="right">' + (i + 1) + '. ' + '</td><td>' + '<span onclick = \"window.open(\'https:\/\/trophymanager.com\/players\/' + soldArr[i].Id + '\')\">' + soldArr[i].Name + '</span>' + '</td><td align="right">' + soldArr[i].Season + '</td><td align="right">' + soldArr[i].Price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td></tr>'; } topSold_content += "</table>"; $("#topSold_content").append(topSold_content); } if (tradeArr.length > 0) { var topTrade_content = "<table>" + "<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>"; for (let i = 0; i < tradeArr.length && i < topCount; i++) { topTrade_content += '<tr><td align="right">' + (i + 1) + '. ' + '</td><td>' + '<span onclick = \"window.open(\'https:\/\/trophymanager.com\/players\/' + tradeArr[i].Id + '\')\">' + tradeArr[i].Name + '</span>' + '</td><td align="right">' + tradeArr[i].Buy.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + tradeArr[i].Sell.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td><td align="right">' + tradeArr[i].Profit.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '</td></tr>'; } topTrade_content += "</table>"; $("#topTrade_content").append(topTrade_content); } } function setTopCount() { let topCount = $('#tm_script_input_top_number')[0].value; if (topCount == '') { localStorage.removeItem(APPLICATION_PARAM.LOCAL_STORAGE_KEY); } else if (isNaN(topCount) || topCount <= 0) { alert('Top count must be positive integer'); } else { localStorage.setItem(APPLICATION_PARAM.LOCAL_STORAGE_KEY, topCount); alert('Set successful, please refresh'); } } })();