// ==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 (https://greasyfork.org/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 // @downloadURL 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 = "
" + "
" + "

Summary Transfer (M)

" + "
" + "
" + "
" + "
" + "
" + "
" + "
" + "
" + "
"; $(".column3_a").append(summaryTransfer); var summaryTransfer_content = "" + ""; var totalBought = 0, totalSold = 0, totalQuantity = 0; transferSummary.forEach((summary) => { summaryTransfer_content += ''; totalBought += summary.Bought; totalSold += summary.Sold; totalQuantity += summary.Quantity; }); summaryTransfer_content += ''; summaryTransfer_content += ''; summaryTransfer_content += "
SSBuySell+-#Avg
' + summary.Season + '' + summary.Bought.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + summary.Sold.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + summary.Balance.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + summary.Quantity + '' + summary.Average.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '
Average' + (totalBought / transferSummary.length).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + (totalSold / transferSummary.length).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + (Math.round(totalSold / transferSummary.length) - Math.round(totalBought / transferSummary.length)).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + (totalQuantity / transferSummary.length).toFixed(0) + '' + (totalQuantity > 0 ? ((totalSold + totalBought) / totalQuantity).toFixed(1).replace(/\B(?=(\d{3})+(?!\d))/g, ",") : 0) + '
Total' + totalBought.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + totalSold.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + (totalSold - totalBought).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + totalQuantity.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + '
"; $("#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 = "
" + "
" + "

Academy Transfer (M)

" + "
" + "
" + "
" + "
" + "
" + "
" + "
" + "
" + "
"; $(".column3_a").append(academyTransfer); var academyTransfer_content = "" + ""; var totalSold = 0, totalQuantity = 0; academySummary.forEach((summary) => { academyTransfer_content += ''; totalSold += summary.Sold; totalQuantity += summary.Quantity; }); academyTransfer_content += ''; academyTransfer_content += ''; academyTransfer_content += "
SSSold#Avg
' + summary.Season + '' + summary.Sold.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + summary.Quantity + '' + summary.Average.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '
Average' + (totalSold / academySummary.length).toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + (totalQuantity / academySummary.length).toFixed(0) + '' + (totalQuantity > 0 ? (totalSold / totalQuantity).toFixed(1).replace(/\B(?=(\d{3})+(?!\d))/g, ",") : 0) + '
Total' + totalSold.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + totalQuantity.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + '
"; $("#academyTransfer_content").append(academyTransfer_content); } function presentTransferStatistic() { var tradeStatistic = "
" + "
" + "

Trade Statistic (M)

" + "
" + "
" + "
" + "" + "Set top count" + "

TOP BOUGHT

" + "
" + "

TOP SOLD

" + "
" + "

TOP TRADE PROFIT

" + "
" + "
" + "
" + "
" + "
" + "
"; $(".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 = "" + ""; for (let i = 0; i < boughtArr.length && i < topCount; i++) { topBought_content += ''; } topBought_content += "
#PlayerSSPrice
' + (i + 1) + '. ' + '' + '' + boughtArr[i].Name + '' + '' + boughtArr[i].Season + '' + boughtArr[i].Price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '
"; $("#topBought_content").append(topBought_content); } if (soldArr.length > 0) { var topSold_content = "" + ""; for (let i = 0; i < soldArr.length && i < topCount; i++) { if (soldArr[i].YoungAcademy) { topSold_content += ""; } else { topSold_content += ""; } topSold_content += ''; } topSold_content += "
#PlayerSSPrice
' + (i + 1) + '. ' + '' + '' + soldArr[i].Name + '' + '' + soldArr[i].Season + '' + soldArr[i].Price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '
"; $("#topSold_content").append(topSold_content); } if (tradeArr.length > 0) { var topTrade_content = "" + ""; for (let i = 0; i < tradeArr.length && i < topCount; i++) { topTrade_content += ''; } topTrade_content += "
#PlayerBuySellProfit
' + (i + 1) + '. ' + '' + '' + tradeArr[i].Name + '' + '' + tradeArr[i].Buy.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + tradeArr[i].Sell.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '' + tradeArr[i].Profit.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '
"; $("#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'); } } })();