tobias88 / Pmanager.org Players

// ==UserScript==
// @name		  Pmanager.org Players
// @namespace	  http://tampermonkey.net/
// @description   That script use the player datas in Pmanager.org website
// @include		  https://www.pmanager.org/ver_jogador.asp?jog_id=*
// @require	      http://code.jquery.com/jquery-latest.js
// @version	      2.02
// @license	      MIT
// @grant		  GM_xmlhttpRequest
// ==/UserScript==

let $ = window.$;

const divStyle = "<div style=\"color:white; background-color:black;\" align=\"center\">";

$(document).ready(function()
{
	// Get Player ID, consider new bigger IDs
	let playerId = (document.URL).substr(48,8);
	if (playerId.indexOf("#",0) > 0 )
		playerId = playerId.substr(0,7);

	// error, the page is not loaded completely
	if ( ($("div#contents").eq(1).find("tr").eq(0).text()).length == 0)
		return;
	//Get end parse data
	GM_xmlhttpRequest({
		method: "GET",
		url: "http://www.pmanagertutorial.nhely.hu/pm_piac/json.php?name=json_name&password=json_password&id="+playerId,
		onload: function (xhr)
		{
			let dataSet;
			//const xhr = '[{"Poszt":"KP B","Nev":"E. Davis","ID":"16338187","Kor":"22","Vedes":"4","Keresztezes":"2","Reflex":"5","Hatarozottsag":"6","Szereles":"10","Fejjatek":"7","Atadas":"20","Helyezkedes":"17","Golszerzes":"1","Technika":"1","Gyorsasag":"4","Ero":"19","Datum":"2018-05-04","GS":"71.2%","Orszag":"23","Adottsag":"Nincs","Tehetseg":"Gyenge\\n"}]';
			try
			{
				dataSet = JSON.parse(xhr.responseText);
			}
			catch(e)
			{
				dataSet = eval("(" + xhr.responseText + ")");
			}
			const data = dataSet[0];
			data.professionalism = getProfessionalism();
			data.position = getPosition();
			const onSale = isOnTransferList(data);
			getCurrentTalents(data);

			if (data.ID != "?" && !onSale)
				showData(data);
			else
				showNoDataMessage();
		}
	});

});

// required because the position could change
function getPosition()
{
	let position = "";
	let positionIndex = 1;
	while ((position.length < 1 || !(/^[A-Z]+$/.test(position))) && positionIndex < 5)
	{
		position = $("div#infos").find("tr").eq(positionIndex).find("b").eq(1).text();
		++positionIndex;
	}
	if (position == "Ifi")
	{
		position = $("div#infos").find("tr").eq(1).find("td.team_players").eq(1).text();
		const start = position.indexOf("(");
		position = position.substring(start + 1, start + 3).trim();
	}
	return position;
}

function getProfessionalism()
{
	// 0-Pocsék(11.66), 1-Csapnivaló(23.33), 2-Átlagos(35), 3-Átlagos(46.66), 4-Jó(58.33), 5-Remek(70)
	return Math.ceil(parseFloat($("table#table1").find("tbody").find("tr").eq(6).find("img").eq(1).attr("width")) / 12);
}

function isOnTransferList(data)
{
	let onSale = $("div#principais").find("td").eq(3).text() != "?";
	if (!onSale)
	{
		const saveDate = new Date(data.Datum);
		if ($("div#contents").eq(1).find("b").eq(0).text().slice(-1) == ":")
		{
			const from = $("div#contents").eq(1).find("td.team_players").eq(0).text().slice(-10).split("/");
			const watchDate = new Date(from[2], from[1] - 1, from[0]);
			if (watchDate < saveDate)
			{
				onSale = false;
			}
		}
	}
	return onSale;
}

function getCurrentTalents(data)
{
	const sideAttrHolder = $("div#contents").find("table.table_border").eq(5);
	data.CurrentTalentStr = sideAttrHolder.find("td").eq(6).text().trim();
	data.NextTalentStr = sideAttrHolder.find("td").eq(8).text().trim();
}

// Attributes
function getGkeAttr(data)
{
	return {
		pri1: data.Vedes, pri2: data.Keresztezes,
		sec1: data.Reflex, sec2: data.Hatarozottsag,
		phy1: data.Gyorsasag, phy2: data.Ero,
		oth1: data.Atadas, oth2: data.Fejjatek, oth3: data.Szereles, oth4: data.Golszerzes, oth5: data.Technika, oth6: data.Helyezkedes,
	};
}
function getDefAttr(data)
{
	return {
		pri1: data.Szereles, pri2: data.Fejjatek,
		sec1: data.Atadas, sec2: data.Helyezkedes,
		phy1: data.Gyorsasag, phy2: data.Ero,
		oth1: data.Technika, oth2: data.Golszerzes, oth3: data.Vedes, oth4: data.Keresztezes, oth5: data.Reflex, oth6: data.Hatarozottsag,
	};
}
function getMidAttr(data)
{
	return {
		pri1: data.Atadas, pri2: data.Helyezkedes,
		sec1: data.Szereles, sec2: data.Technika,
		phy1: data.Gyorsasag, phy2: data.Ero,
		oth1: data.Fejjatek, oth2: data.Golszerzes, oth3: data.Vedes, oth4: data.Keresztezes, oth5: data.Reflex, oth6: data.Hatarozottsag,
	};
}
function getStrAttr(data)
{
	return {
		pri1: data.Golszerzes, pri2: data.Technika,
		sec1: data.Fejjatek, sec2: data.Helyezkedes,
		phy1: data.Gyorsasag, phy2: data.Ero,
		oth1: data.Atadas, oth2: data.Szereles, oth3: data.Vedes, oth4: data.Keresztezes, oth5: data.Reflex, oth6: data.Hatarozottsag,
	};
}

// Display
function showData(data)
{
	// Main and secondary attributes
	const mainAttributes = $("div#principais").find("td");
	const secondaryAttributes = $("div#terciarios").find("td");
	let attributes;
	if (data.position == "GK")
		attributes = getGkeAttr(data);
	else if (data.position == "V")
		attributes = getDefAttr(data);
	else if (data.position == "KP")
		attributes = getMidAttr(data);
	else if (data.position == "T")
		attributes = getStrAttr(data);

	mainAttributes. eq(3).html(divStyle + attributes.pri1 + "</div>");
	mainAttributes. eq(7).html(divStyle + attributes.pri2 + "</div>");
	mainAttributes.eq(12).html(divStyle + attributes.sec1 + "</div>");
	mainAttributes.eq(16).html(divStyle + attributes.sec2 + "</div>");
	mainAttributes.eq(21).html(divStyle + attributes.phy1 + "</div>");
	mainAttributes.eq(25).html(divStyle + attributes.phy2 + "</div>");

	secondaryAttributes. eq(3).html(divStyle + attributes.oth1 + "</div>");
	secondaryAttributes. eq(7).html(divStyle + attributes.oth2 + "</div>");
	secondaryAttributes.eq(11).html(divStyle + attributes.oth3 + "</div>");
	secondaryAttributes.eq(15).html(divStyle + attributes.oth4 + "</div>");
	secondaryAttributes.eq(19).html(divStyle + attributes.oth5 + "</div>");
	secondaryAttributes.eq(23).html(divStyle + attributes.oth6 + "</div>");

	// Other Attributes
	const attrChanges = getAttrChanges(data);
	$("div#contents").eq(1).find("tr").eq(0).html(divStyle+
												"<u>"+data.Datum+":</u>&nbsp;"+
												"&nbsp;"+data.Kor+" év"+
												"&nbsp;&nbsp;|&nbsp;&nbsp;"+
												"Változás ("+ data.Tehetseg.trim() +"):&nbsp; +"+ attrChanges.plus +" | -" +
												Math.round(10 * attrChanges.minus / 12) / 10 + "/db" +
												"&nbsp;&nbsp;|&nbsp;&nbsp;"+
												$("div#contents").eq(1).find("tr").eq(0).text() +
												"</div>");
	// talent
	$("div#contents").eq(1).find("table").eq(1).find("td").eq(64).html(divStyle + data.Adottsag + "</div>");
}

function showNoDataMessage()
{
	$("div#contents").eq(1).find("tr").eq(0).html(divStyle+"|&nbsp;&nbsp;"+
													"Nincs adat!"+
													"&nbsp;&nbsp;|&nbsp;&nbsp;"+
													$("div#contents").eq(1).find("tr").eq(0).text() +
													"&nbsp;&nbsp;|</div>");
}

// Tools

const dayPerSeason = 77; // 11 weeks
const dayPerPreSeason = 14;// 2 weeks
const dayPerMainSeason = 63;// 9 weeks
Date.prototype.addDays = function(days)
{
	const date = new Date(this.valueOf());
	date.setDate(date.getDate() + days);
	return date;
};
Date.prototype.getDayDiffTo = function(days)
{
	return Math.floor(this.valueOf() - days) / (1000 * 60 * 60 * 24);
};
Date.prototype.getSeasonDiffTo = function(days)
{
	return Math.floor(this.getDayDiffTo(days) / dayPerSeason);
};

function getReducePerDay(age, professionalism)
{
	if (age >= firstMaxTouchedYear)
		return 0.1; // around 0.66*12 per season
	const reduce = (age - lastUntouchedYear - professionalism / 2) * 0.02;
	return Math.max(reduce, 0); // I did not found the table so who knows
}

const talentReducePerSeason = 0.75;
const trainingReduce = 0.75;
const matchesPreSeason = 1.5;
const matchesMainSeason = 22.5; // 18 + 9 friendly
const lastMaxTalentYear = 20;
const lastMinFittYear = 23;
const lastUntouchedYear = 26;
const firstMaxTouchedYear = 32;
function getTalentLevel(talentString)
{
	if (talentString == "Pocsék")
	{
		return 0;
	}
	if (talentString == "Csapnivaló")
	{
		return 1;
	}
	if (talentString == "Nagyon gyenge")
	{
		return 2;
	}
	if (talentString == "Gyenge")
	{
		return 3;
	}
	if (talentString == "Megfelelo" || talentString == "Megfelelő")
	{
		return 4;
	}
	if (talentString == "Jó")
	{
		return 5;
	}
	if (talentString == "Nagyon jó")
	{
		return 6;
	}
	if (talentString == "Remek")
	{
		return 7;
	}
	if (talentString == "Nagyszeru" || talentString == "Nagyszerű")
	{
		return 8;
	}
	if (talentString == "Világklasszis")
	{
		return 9;
	}
	console.log("ERROR, unknown Talent!");
	return 0;
}
function getTalentMax(talentString)
{
	return 0.04 + 0.05 * getTalentLevel(talentString);
}
function getStoreTalent(storedAge, storedTalent, currentAge, currentTalent, nextTalent)
{
	const storedMax = getTalentMax(storedTalent.slice(0,-1));
	let currentMax = getTalentMax(currentTalent);
	let nextMax = getTalentMax(nextTalent);
	currentMax *= Math.pow(1 / talentReducePerSeason, currentAge - lastMaxTalentYear);
	nextMax *= Math.pow(1 / talentReducePerSeason, currentAge - lastMaxTalentYear + 1); // because of it's next year
	return Math.min(storedMax, currentMax, nextMax);
}

function getAttrChanges(data)
{
	let positive = 0;
	let negative = 0;
	let startOfSeason = new Date("2014-09-01");
	const storeDate = new Date(data.Datum);
	const currentDate = new Date();
	let age = parseInt(data.Kor);
	let trainerlessTalentActive = false;
	// set first valid season date
	startOfSeason = startOfSeason.addDays((storeDate.getSeasonDiffTo(startOfSeason) + 1) * dayPerSeason);
	let talent = getStoreTalent(age, data.Tehetseg, currentDate.getSeasonDiffTo(startOfSeason) + age + 1, data.CurrentTalentStr, data.NextTalentStr);
	// first season usually not full
	let dayThisSeason = startOfSeason > currentDate ? currentDate.getDayDiffTo(storeDate) : startOfSeason.getDayDiffTo(storeDate);
	while(startOfSeason < currentDate.addDays(dayPerSeason))
	{
		// last season usually not full
		if (dayThisSeason == dayPerSeason && startOfSeason > currentDate)
		{
			dayThisSeason = currentDate.getDayDiffTo(startOfSeason) + dayPerSeason;
		}
		negative += getReducePerDay(age, data.professionalism) * dayThisSeason;
		// From 24 the trainer does not worth it
		// After this use the trainerless talent
		if (age > lastMinFittYear && !trainerlessTalentActive)
		{
			trainerlessTalentActive = true;
			talent *= trainingReduce;
		}
		// preseason
		positive += talent * matchesPreSeason * Math.min(dayThisSeason, dayPerPreSeason) / dayPerPreSeason;
		dayThisSeason -= dayPerPreSeason;
        // mainseason
		if (dayThisSeason > 0) // considering fittness -> based on experience
			positive += talent * matchesMainSeason * Math.min(dayThisSeason, dayPerMainSeason) / dayPerMainSeason *
				(1 - Math.max(Math.min(age - lastMinFittYear, 0.2),0));
		// ready for next loop
		startOfSeason = startOfSeason.addDays(dayPerSeason);
		++age;
		if (age > lastMaxTalentYear)
		{
			talent *= talentReducePerSeason;
		}
		dayThisSeason = dayPerSeason;
	}
	return {
		plus: Math.ceil(positive * 10) / 10,
		minus: Math.ceil(negative * 10) / 10,
	};
}