Ranked War Reward Split

try to take over the world!

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

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.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Ranked War Reward Split
// @namespace    http://tampermonkey.net/
// @version      0.4
// @description  try to take over the world!
// @author       Daviid-P[2851873]
// @match        https://www.torn.com/war.php?step=rankreport&rankID=*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=torn.com
// @grant        none
// @license      GNU GPLv3
// ==/UserScript==

let factionMembers; // Declare factionMembers as a global variable
let totalPoints; // Declare totalPoints as a global variable

(function () {
  "use strict";

  const isElementLoaded = async (selector) => {
    while (document.querySelector(selector) === null) {
      await new Promise((resolve) => requestAnimationFrame(resolve));
    }
    return document.querySelector(selector);
  };

  // Wait for the faction members list to load and then execute the main function
  isElementLoaded("ul.members-list li").then((factions_members_list) => {
    main();
  });
})();

function main() {
  let factions_members_list = document.querySelectorAll("ul.members-list");
  let player_name = document
    .querySelector("script[donator]")
    .getAttribute("name");

  const our_faction_list = Array.from(factions_members_list).find(
    (faction_members_list) =>
      faction_members_list.textContent.includes(player_name)
  );

  const open_dialog_button = createDialogButton(our_faction_list);
  const clearDiv = our_faction_list.parentNode.querySelector("div div.clear");

  // Prepend the button element to the parent of our_faction_list
  if (our_faction_list && our_faction_list.parentNode) {
    our_faction_list.parentNode.insertBefore(
      open_dialog_button,
      our_faction_list
    );
  }

  factionMembers = our_faction_list.querySelectorAll("li");
  totalPoints = Array.from(factionMembers)
    .slice(0, -1)
    .reduce((sum, member) => {
      const memberPoints = parseFloat(
        member.querySelector(".status").textContent
      );
      return sum + memberPoints;
    }, 0);

  const rewardPerAttackHeader = createRewardHeader("1m x Hit");
  const rewardPercentageHeader = createRewardHeader("80/20");

  // Insert column headers before the "clear" div
  clearDiv.parentNode.insertBefore(rewardPerAttackHeader, clearDiv);
  clearDiv.parentNode.insertBefore(rewardPercentageHeader, clearDiv);

  // Initial update of rewards with default values
  updateRewards(0, 0.8, 1000000);
}

// Function to create the open dialog button
function createDialogButton(our_faction_list) {
  const open_dialog_button = document.createElement("button");
  open_dialog_button.textContent = "Open Dialog";
  open_dialog_button.className = "btn btn-primary"; // Add class names
  open_dialog_button.addEventListener("click", () => {
    createDialog();
  });
  return open_dialog_button;
}

// Function to create a column header element
function createRewardHeader(text) {
  const rewardHeader = document.createElement("div");
  rewardHeader.textContent = text;
  rewardHeader.className = "reward-header left";
  rewardHeader.style = "width: 70px; margin-right: 10px;";
  return rewardHeader;
}

// Function to create the dialog element
function createDialog() {
  const dialog = document.createElement("dialog");
  dialog.style.display = "flex";
  dialog.style.flexDirection = "column";
  dialog.style.width = "200px";
  dialog.style.height = "200px";
  dialog.style.justifyContent = "space-around";

  const cacheSellingPriceInputContainer = createNumberInput(
    "Enter reward amount",
    "Reward Amount"
  );
  const rewardDistributionSliderContainer = createSliderInput(
    0,
    100,
    1,
    80,
    "Reward Distribution"
  );
  const pricePerHitInputContainer = createNumberInput(
    "Enter price per hit",
    "Price per Hit"
  );

  const updateButton = document.createElement("button");
  updateButton.textContent = "Update Rewards";
  updateButton.className = "btn btn-primary"; // Add class names
  updateButton.addEventListener("click", () => {
    const cacheSellingPriceInput =
      cacheSellingPriceInputContainer.querySelector("input");
    const rewardDistributionSlider =
      rewardDistributionSliderContainer.querySelector("input");
    const pricePerHitInput = pricePerHitInputContainer.querySelector("input");

      console.error(cacheSellingPriceInput.value)
      console.error(parseLocaleNumber(cacheSellingPriceInput.value))
    const cacheSellingPrice = parseFloat(parseLocaleNumber(cacheSellingPriceInput.value));
    const rewardDistribution = parseFloat(parseLocaleNumber(rewardDistributionSlider.value)) / 100;
    const pricePerHit = parseFloat(parseLocaleNumber(pricePerHitInput.value));
    console.error(
      cacheSellingPrice,
      rewardDistribution,
      pricePerHit
    );

    updateRewards(cacheSellingPrice, rewardDistribution, pricePerHit);

    // Close the dialog after updating the rewards
    dialog.close();
  });

  dialog.appendChild(cacheSellingPriceInputContainer);
  dialog.appendChild(rewardDistributionSliderContainer);
  dialog.appendChild(pricePerHitInputContainer);
  dialog.appendChild(updateButton);

  document.body.appendChild(dialog);
  dialog.showModal();
}

// Function to create a number input element with a label
// Function to create a number input element with a label
function createNumberInput(placeholder, label) {
  const container = document.createElement("div");
  container.style.display = "flex";
  container.style.flexDirection = "column";
  container.style.marginBottom = "10px";

  const labelText = document.createElement("label");
  labelText.textContent = label;

  const numberInput = document.createElement("input");
  numberInput.placeholder = placeholder;
  numberInput.style.padding = "5px";
  numberInput.style.fontSize = "14px";
  numberInput.style.border = "1px solid #ccc";
  numberInput.pattern = "^d{1,3}(,d{3})*(.d+)?$";
  numberInput.dataset.type = "currency";
  numberInput.placeholder = "1,000,000";

  // Add event listeners for formatting the input value with thousands separators
  numberInput.addEventListener("input", formatCurrency);

  container.appendChild(labelText);
  container.appendChild(numberInput);

  return container;
}

// Function to create a slider input element with a label
function createSliderInput(min, max, step, value, label) {
  const container = document.createElement("div");
  container.style.display = "flex";
  container.style.flexDirection = "column";
  container.style.marginBottom = "10px";

  const labelText = document.createElement("label");
  labelText.textContent = label;

  const sliderContainer = document.createElement("div");
  sliderContainer.style.display = "flex";
  sliderContainer.style.alignItems = "center";

  const sliderInput = document.createElement("input");
  sliderInput.type = "range";
  sliderInput.min = min.toString();
  sliderInput.max = max.toString();
  sliderInput.step = step.toString();
  sliderInput.value = value.toString();
  sliderInput.style.flexGrow = "1";

  const valueSpan = document.createElement("span");
  valueSpan.textContent = value.toString();
  valueSpan.style.marginLeft = "10px";

  sliderInput.addEventListener("input", () => {
    valueSpan.textContent = sliderInput.value;
  });

  sliderContainer.appendChild(sliderInput);
  sliderContainer.appendChild(valueSpan);

  container.appendChild(labelText);
  container.appendChild(sliderContainer);

  return container;
}

// Function to update rewards based on the cache selling price, reward distribution, and price per hit
function updateRewards(cacheSellingPrice, rewardDistribution, pricePerHit) {
      const rewardPerAttackHeader = document.querySelector(".reward-header.left");
  const rewardPercentageHeader = document.querySelector(".reward-header.left + .reward-header");

  rewardPerAttackHeader.textContent = `${formatNumberShort(pricePerHit)} x Hit`;
  rewardPercentageHeader.textContent = `${(rewardDistribution * 100).toFixed(0)}/${100-(rewardDistribution * 100).toFixed(0)}`;

  const membersToIterate = Array.from(factionMembers).slice(0, -1);
  membersToIterate.forEach((member) => {
    let clearDiv = member.querySelector("div.clear");
    const memberAttacks = parseFloat(
      member.querySelector(".points").textContent
    );
    const memberPoints = parseFloat(
      member.querySelector(".status").textContent
    );
    const memberId = new URLSearchParams(document.querySelector("div.member a").href).get("ID");

    let rewardPerAttack = member.querySelector(".reward-per-attack");
    let rewardPercentage = member.querySelector(".reward-percentage");

    if (!rewardPerAttack) {
      rewardPerAttack = document.createElement("div");
      rewardPerAttack.className = "reward-per-attack left";
      rewardPerAttack.style =
        "width: 70px; height: 33px; line-height: 36px; text-align: right; padding-right: 10px; margin-right: 10px;";
      member.insertBefore(rewardPerAttack, clearDiv);
    }

    if (!rewardPercentage) {
      rewardPercentage = document.createElement("div");
      rewardPercentage.className = "reward-percentage left";
      rewardPercentage.style =
        "width: 70px; height: 33px; line-height: 36px; text-align: right; padding-right: 10px; margin-right: 10px;";
      member.insertBefore(rewardPercentage, clearDiv);
    }

    const textSpan = document.createElement("span");

    while (rewardPerAttack.firstChild) {
      rewardPerAttack.removeChild(rewardPerAttack.firstChild);
    }
    while (rewardPercentage.firstChild) {
      rewardPercentage.removeChild(rewardPercentage.firstChild);
    }

    const attacks = memberAttacks * pricePerHit;
    rewardPerAttack.textContent = attacks;
    rewardPerAttack.innerHTML = `<a href="https://www.torn.com/factions.php?step=your#/tab=controls&option=pay-day&select=${memberId}&pay=${attacks}">${attacks.toLocaleString()}</a>`;

    const reward = Math.floor(
      (memberPoints / totalPoints) * (cacheSellingPrice * rewardDistribution)
    );
    rewardPercentage.innerHTML = `<a href="https://www.torn.com/factions.php?step=your#/tab=controls&option=pay-day&select=${memberId}&pay=${reward}">${reward.toLocaleString()}</a>`;
  });
}

function parseLocaleNumber(stringNumber) {
  var thousandSeparator = Intl.NumberFormat("en-EN")
    .format(11111)
    .replace(/\p{Number}/gu, "");
  var decimalSeparator = Intl.NumberFormat("en-EN")
    .format(1.1)
    .replace(/\p{Number}/gu, "");

  return parseFloat(
    stringNumber
      .replace(new RegExp("\\" + thousandSeparator, "g"), "")
      .replace(new RegExp("\\" + decimalSeparator), ".")
  );
}

function formatNumber(n) {
  // format number 1000000 to 1,234,567
  return n.replace(/\D/g, "").replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

function formatNumberShort(number) {
const suffixes = ["", "k", "m", "b", "t"];
let suffixIndex = 0;
while (number >= 1000 && suffixIndex < suffixes.length - 1) {
number /= 1000;
suffixIndex++;
}
return number.toLocaleString() + suffixes[suffixIndex];
}

function formatCurrency(event) {
  // appends $ to value, validates decimal side
  // and puts cursor back in right position.

  let input = event.target;
  let blur = event.type;

  // get input value
  var input_val = input.value;

  // dont validate empty input
  if (input_val === "") {
    return;
  }

  // original length
  var original_len = input_val.length;

  // initial caret position
  var caret_pos = input.selectionStart;

  // check for decimal
  if (input_val.indexOf(".") >= 0) {
    // get position of first decimal
    // this prevents multiple decimals from
    // being entered
    var decimal_pos = input_val.indexOf(".");

    // split number by decimal point
    var left_side = input_val.substring(0, decimal_pos);
    var right_side = input_val.substring(decimal_pos);

    // add commas to left side of number
    left_side = formatNumber(left_side);

    // validate right side
    right_side = formatNumber(right_side);

    // On blur make sure 2 numbers after decimal
    if (blur === "blur") {
      right_side += "00";
    }

    // Limit decimal to only 2 digits
    right_side = right_side.substring(0, 2);

    // join number by .
    input_val = left_side + "." + right_side;
  } else {
    // no decimal entered
    // add commas to number
    // remove all non-digits
    input_val = formatNumber(input_val);
    input_val = input_val;

    // final formatting
    if (blur === "blur") {
      input_val += ".00";
    }
  }

  // send updated string to input
  input.value = input_val;

  // put caret back in the right position
  var updated_len = input_val.length;
  caret_pos = updated_len - original_len + caret_pos;
  input.setSelectionRange(caret_pos, caret_pos);
}

function addCustomCSS(css) {
  const styleElement = document.createElement("style");
  styleElement.textContent = css;

  const headElement = document.querySelector("head");
  headElement.appendChild(styleElement);
}

// CSS styles
const customCSS = `
  .btn {
    display: inline-block;
    font-weight: 400;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    user-select: none;
    border: 1px solid transparent;
    padding: 0.375rem 0.75rem;
    font-size: 1rem;
    line-height: 1.5;
    border-radius: 0.25rem;
    cursor: pointer;
    transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
  }

  .btn-primary {
    color: #fff;
    background-color: #007bff;
    border-color: #007bff;
  }

  .reward-per-attack a,
  .reward-percentage a{
    text-decoration: none;
    color: inherit;
  }
`;

// Add custom CSS to the document
addCustomCSS(customCSS);