// ==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 = "" +
"SS | Buy | Sell | +- | # | Avg |
";
var totalBought = 0,
totalSold = 0,
totalQuantity = 0;
transferSummary.forEach((summary) => {
summaryTransfer_content +=
'' + 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, ",") +
' |
';
totalBought += summary.Bought;
totalSold += summary.Sold;
totalQuantity += summary.Quantity;
});
summaryTransfer_content +=
'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) + ' |
';
summaryTransfer_content +=
'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 += "
";
$("#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 = "" +
"SS | Sold | # | Avg |
";
var totalSold = 0,
totalQuantity = 0;
academySummary.forEach((summary) => {
academyTransfer_content +=
'' + summary.Season +
' | ' + summary.Sold.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
' | ' + summary.Quantity +
' | ' + summary.Average.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
' |
';
totalSold += summary.Sold;
totalQuantity += summary.Quantity;
});
academyTransfer_content +=
'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) + ' |
';
academyTransfer_content +=
'Total | ' +
totalSold.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + ' | ' +
totalQuantity.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + ' | ' +
' |
';
academyTransfer_content += "
";
$("#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 = "" +
"# | Player | SS | Price |
";
for (let i = 0; i < boughtArr.length && i < topCount; i++) {
topBought_content +=
'' + (i + 1) + '. ' +
' | ' + '' + boughtArr[i].Name + '' +
' | ' + boughtArr[i].Season +
' | ' + boughtArr[i].Price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
' |
';
}
topBought_content += "
";
$("#topBought_content").append(topBought_content);
}
if (soldArr.length > 0) {
var topSold_content = "" +
"# | Player | SS | Price |
";
for (let i = 0; i < soldArr.length && i < topCount; i++) {
if (soldArr[i].YoungAcademy) {
topSold_content += "";
} else {
topSold_content += "
";
}
topSold_content +=
'' + (i + 1) + '. ' +
' | ' + '' + soldArr[i].Name + '' +
' | ' + soldArr[i].Season +
' | ' + soldArr[i].Price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") +
' |
';
}
topSold_content += "
";
$("#topSold_content").append(topSold_content);
}
if (tradeArr.length > 0) {
var topTrade_content = "" +
"# | Player | Buy | Sell | Profit |
";
for (let i = 0; i < tradeArr.length && i < topCount; i++) {
topTrade_content +=
'' + (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 += "
";
$("#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');
}
}
})();