Greasy Fork

Greasy Fork is available in English.

TMVN Club Transfer

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).

当前为 2021-04-15 提交的版本,查看 最新版本

// ==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');
		}
	}
})();