TM Value Variation Calculator

Calculates sell to agent current and old values, based on the RatingR5 (ver5.4 for Season67) local storage.

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Greasemonkey lub Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Violentmonkey.

Aby zainstalować ten skrypt, wymagana będzie instalacja rozszerzenia Tampermonkey lub Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

Aby zainstalować ten skrypt, musisz zainstalować rozszerzenie menedżera skryptów użytkownika.

(Mam już menedżera skryptów użytkownika, pozwól mi to zainstalować!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

Będziesz musiał zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

Będziesz musiał zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

Musisz zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

(Mam już menedżera stylów użytkownika, pozwól mi to zainstalować!)

/**
 * TM Value Variation Calculator - a.k.a. SIS (Should I sell?)
 * version 0.0.1 BETA - only English
 */

// ==UserScript==
// @name         TM Value Variation Calculator
// @namespace    http://tampermonkey.net/
// @version      0.0.1 Beta - English Only (2023-12-14)
// @description  Calculates sell to agent current and old values, based on the RatingR5 (ver5.4 for Season67) local storage.
// @author       Erik (ABC FC 4402678)
// @include      https://trophymanager.com/players/*
// @exclude      https://trophymanager.com/players/compare/*
// @exclude      https://trophymanager.com/players/
// @icon         https://www.google.com/s2/favicons?sz=64&domain=trophymanager.com
// @grant        none
// @license      MIT
// ==/UserScript==

function calcSellToAgentPrice(ASI, ageMonths) {
  const MP = Math.pow;
  const notGK = player_fp != "gk" ? true : false;
  let staPrice; // Sell To Agent Price
  if (notGK) {
    staPrice = parseInt(ASI * 500 * MP(300 / ageMonths, 2.5));
  } else {
    staPrice = parseInt(ASI * 500 * MP(300 / ageMonths, 2.5) * 0.75);
  }
  const maxPrice = parseInt(ASI * (192400 / (ageMonths / 12) - 5200));
  if (maxPrice < staPrice) maxPrice = staPrice;
  return { staPrice, maxPrice };
}

/**
 * @param {string} age 'e.g. 30 Years 11 Months'
 * @returns {Object} { ageMonths, month, year }
 */
function formatAge(age) {
  const yearIndex = age.search(/\d\d/);
  const year = Number(age.substr(yearIndex, 2));
  age = age.slice(yearIndex + 2);
  const month = Number(age.replace(/\D+/g, ""));
  const ageMonths = year * 12 + month * 1;
  return { ageMonths, month, year };
}

/**
 * @returns {string} 'e.g. "30 Years 11 Months".'
 */
function getAge() {
  const getTr = document.getElementsByTagName("tr");
  let age = null;
  for (let i = 0; i < getTr.length; i++) {
    const currentTr = getTr[i]?.getElementsByTagName("td")[0]?.innerHTML;
    if (currentTr?.includes("Years")) {
      // Only english || currentTr.includes("Anos")
      age = currentTr;
      break;
    }
  }
  return age;
}

function getAsi() {
  const getTr = document.getElementsByTagName("tr");
  let asi = null;
  for (let i = 0; i < getTr.length; i++) {
    const currentTr = getTr[i]?.innerHTML;
    if (currentTr?.includes("Skill Index")) {
      const match = currentTr.match(/<td>([\d,]+)<\/td>/); // e.g. '<th>Skill Index</th><td>125,701</td>'
      if (match && match.length === 2) {
        const numberValue = match[1];
        asi = parseFloat(numberValue.replace(/,/g, ""));
      }
      break;
    }
  }
  return asi;
}

function getWage() {
  const getTr = document.getElementsByTagName("tr");
  let wage = null;
  for (let i = 0; i < getTr.length; i++) {
    const currentTr = getTr[i]?.innerHTML;
    if (currentTr?.includes("Wage")) {
      const match = currentTr.match(
        /<td><span class="coin">([\d,]+)<\/span><\/td>/
      );
      if (match && match.length === 2) {
        const numberValue = match[1];
        wage = parseFloat(numberValue.replace(/,/g, ""));
      }
      break;
    }
  }
  return wage;
}

function main() {
  // localStorage from RatingR5 extension(version 5.4 used as reference)
  const ASIObjdata = JSON.parse(localStorage.getItem(player_id + "_SI")); // variable from TM: player_id
  if (!ASIObjdata) {
    console.log(
      "Not enough data recorded from this player. Local storage empty"
    );
    return "Not enough data recorded from this player. Make sure you have R5/R6 installed and that you have visualized this player in the last 6 weeks.\n\nMore info in the <a href='https://github.com/erik-ymmt/TM-Value-Variation-Calculator' target='_blank'>script documentation</a>.";
  }

  const curAge = getAge();
  const curAgeFormated = formatAge(curAge);
  const currentAgeInMonths = curAgeFormated.ageMonths;
  const curAgeString = curAgeFormated.year + "." + curAgeFormated.month;
  const agesASI = Object.keys(ASIObjdata);

  const lastRecordedAgeIndex = agesASI.indexOf(curAgeString);
  if (lastRecordedAgeIndex > -1) agesASI.splice(lastRecordedAgeIndex, 1);

  if (agesASI.length == 0) {
    console.log(
      "Not enough data recorded from this player. Local storage empty"
    );
    return "Not enough data recorded from this player. Make sure you have R5 installed and that you have visualized this player on the last 6 weeks";
  }

  const lastAgeRecorded = agesASI[agesASI.length - 1];
  const lastAgeRecordedInMonths =
    Number(lastAgeRecorded.split(".")[0]) * 12 +
    Number(lastAgeRecorded.split(".")[1]);

  const ageDif = currentAgeInMonths - lastAgeRecordedInMonths;
  if (ageDif > 8) {
    console.log("Data is too old for this player");
    return "Data is too old for this player";
  }

  const lastASI = ASIObjdata[lastAgeRecorded];
  const curASI = getAsi();
  const lastStaPrice = calcSellToAgentPrice(
    lastASI,
    lastAgeRecordedInMonths
  ).staPrice;
  const currentStaPrice = calcSellToAgentPrice(
    curASI,
    currentAgeInMonths
  ).staPrice;
  const wage = getWage();
  const difference = currentStaPrice - lastStaPrice;
  const differencePerWeek = Math.round(difference / ageDif);

  let extraMsg = "";

  if (differencePerWeek < 0) {
    extraMsg += "Your player is losing value. You could consider selling him.";
  } else if (differencePerWeek == 0) {
    extraMsg +=
      "Your player kept his value. You could consider selling him, if his wage is an issue.";
  } else {
    extraMsg += "Your player is gaining value";
    if (wage > differencePerWeek)
      extraMsg +=
        ", but not more than his wage. You could consider selling him.";
    if (wage === differencePerWeek) extraMsg += " that pays his wage.";
    if (wage < differencePerWeek)
      extraMsg +=
        " more than his wage, consider keeping him for a little longer.";
  }

  const message = `
  - Last price recorded: ${lastStaPrice.toLocaleString(
    "en"
  )} (${ageDif} week(s) ago)
  - Total Value Variation: ${difference.toLocaleString(
    "en"
  )} (${ageDif} week(s))
  - Week Value Variation: ${differencePerWeek.toLocaleString("en")}
  - Weekly Wage: ${wage.toLocaleString("en")}
  - Should I sell? ${extraMsg}`;

  const messageDiv = document.createElement("div");
  messageDiv.innerText = `
    ${differencePerWeek - wage > 0 ? "+" : ""}${(
    differencePerWeek - wage
  ).toLocaleString("en")}
    (Week Variation vs. Wage)`;
  messageDiv.style = "text-align: center; font-weight: bold; margin: 16px,0;";
  $("#transferbox").append(messageDiv);

  const messageP = document.createElement("p");
  messageP.innerText = message;
  messageP.style = "text-align: left";
  sisBtn.id = "sisCalculationsInfo";
  $("#transferbox").append(messageP);

  return 0;
}

const sisBtn = document.createElement("button");
sisBtn.textContent = "Calculate Value Variation";
sisBtn.id = "sisBtn";
sisBtn.class = "button button_border";
sisBtn.style =
  "width:168px; height:24px; padding: 1; color:white; background-color:#4A6C1F; cursor:pointer; border:1px solid #6c9922;";
sisBtn.addEventListener("click", function () {
  const sisCalculationsInfo = document.getElementById("sisCalculationsInfo");
  if (!sisCalculationsInfo) {
    const execute = main();
    if (execute != 0) {
      alert(execute);
    }
  } else {
    alert("Calculations already done!");
  }
});

$("#transferbox").append(sisBtn);