TC Bootlegging Plus v2

Tools to help with Bootlegging

目前为 2025-02-27 提交的版本,查看 最新版本

// ==UserScript==
// @name         TC Bootlegging Plus v2
// @namespace   DieselBladeScripts
// @version      0.9
// @description  Tools to help with Bootlegging
// @license     GPLv3
// @author       DieselBlade [1701621]
// @match        *https://www.torn.com/loader.php?sid=crimes*
// @grant        unsafeWindow
// @run-at       document-start
// ==/UserScript==


const originalFetch = fetch;

unsafeWindow.fetch = async (input, init) => {
  const response = await originalFetch(input, init);
  if (input.includes('crimesData')) {
    crimesMain(response.clone()).catch(console.error);
  }
  return response;
};

async function crimesMain(res) {
  const crimesData = await res.json();
  const crimeType = crimesData?.DB?.currentUserStatistics?.[1]?.value;

  if (crimeType === 'Counterfeiting') {
    counterfeiting(crimesData.DB);
  } else {
    console.log(crimesData);
  }
}

async function counterfeiting(db) {
  const { generalInfo, currentUserStats, crimesByType } = db;
  const CDs = {
    have: generalInfo.CDs,
    sold: {
      1: currentUserStats.CDType1Sold,
      2: currentUserStats.CDType2Sold,
      3: currentUserStats.CDType3Sold,
      4: currentUserStats.CDType4Sold,
      5: currentUserStats.CDType5Sold,
      6: currentUserStats.CDType6Sold,
      7: currentUserStats.CDType7Sold,
      8: currentUserStats.CDType8Sold
    },
    genres: {
      'Action': '1',
      'Comedy': '2',
      'Drama': '3',
      'Fantasy': '4',
      'Horror': '5',
      'Romance': '6',
      'Thriller': '7',
      'Sci-Fi': '8'
    }
  };

  const currentQueue = crimesByType?.['0']?.additionalInfo?.currentQueue || [];
  currentQueue.forEach(cdID => CDs.have[cdID] += 1);

  const observer = new MutationObserver(() => {
    const genreButtons = document.querySelectorAll('button[class^=genreStock]');
    if (genreButtons.length > 0) {
      updateGenreButtons(CDs);
      addGuideBox();
      observer.disconnect();
    }
  });

  observer.observe(document, { childList: true, subtree: true });
}

function updateGenreButtons(CDs) {
    const GREEN_HSL = 120;
    const RED_HSL = 0;

    const totalHave = sumValues(CDs.have);
    const totalSold = sumValues(CDs.sold);

    let worstProportion = Infinity;
    let bestProportion = 0;

    // First pass to determine worst and best proportions
    document.querySelectorAll('button[class^=genreStock]').forEach((genreButton) => {
        const genre = genreButton.getAttribute('aria-label').split(' - ')[0].replace('Copying ', '');
        const typeID = CDs.genres[genre];
        const target = Math.floor((CDs.sold[typeID] / totalSold) * totalHave);
        const proportion = CDs.have[typeID] / target;

        if (proportion < worstProportion) {
            worstProportion = proportion;
        }
        if (proportion > bestProportion) {
            bestProportion = proportion;
        }
    });

    // Second pass to assign colors based on relative proportions
    document.querySelectorAll('button[class^=genreStock]').forEach((genreButton) => {
        const genre = genreButton.getAttribute('aria-label').split(' - ')[0].replace('Copying ', '');
        const typeID = CDs.genres[genre];
        const target = Math.floor((CDs.sold[typeID] / totalSold) * totalHave);
        const proportion = CDs.have[typeID] / target;

        // Normalize the proportion based on worst and best
        const normalizedProportion = (proportion - worstProportion) / (bestProportion - worstProportion);
        const h = RED_HSL + normalizedProportion * (GREEN_HSL - RED_HSL);

        genreButton.style.backgroundColor = `hsl(${h}, 100%, 90%)`;

        // Update the text for how many more are needed or if there are excess copies
        const existingDiffText = genreButton.querySelector('.diffText');
        if (existingDiffText) {
            existingDiffText.remove();
        }

        const diff = target - CDs.have[typeID];
        const diffText = document.createElement('div');
        diffText.className = 'diffText'; // Add a class to the diffText for easy selection
        diffText.textContent = diff > 0 ? `${diff} more needed` : 'Excess copies';
        genreButton.appendChild(diffText);
    });
}


function sumValues(obj) {
  return Object.values(obj).reduce((a, b) => a + b, 0);
}

function addGuideBox() {
  const guideBox = document.createElement("div");
  guideBox.style.position = "fixed";
  guideBox.style.top = "10px";
  guideBox.style.right = "10px";
  guideBox.style.backgroundColor = "#333";
  guideBox.style.padding = "10px";
  guideBox.style.border = "2px solid gold";
  guideBox.style.zIndex = "9999";
  guideBox.style.borderRadius = "5px";

  const title = document.createElement("h2");
  title.textContent = "Phantom Scripting";
  title.style.color = "gold";
  title.style.marginBottom = "10px";
  guideBox.appendChild(title);

  const explanation = document.createElement("p");
  explanation.innerHTML = `
    <strong>Color Guide:</strong>
    <br><span style="background-color:hsl(120, 100%, 90%); display:inline-block; width:16px; height:16px; margin-right:4px;"></span> Perfect quantity.
    <br><span style="background-color:hsl(0, 100%, 90%); display:inline-block; width:16px; height:16px; margin-right:4px;"></span> Too few or too many of this genre.
  `;
  explanation.style.color = "white";
  guideBox.appendChild(explanation);

  document.body.appendChild(guideBox);
}