RW MV calculator & buy/sell calculator (customizable)

click green button, get read out. buttons nxt to left numbers put that number * 'buyperc', on right they copy the number they are on

// ==UserScript==
// @name         RW MV calculator & buy/sell calculator (customizable)
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  click green button, get read out. buttons nxt to left numbers put that number * 'buyperc', on right they copy the number they are on
// @author       Tuit
// @match        https://www.torn.com/war.php?step=rankreport&rankID*
// @grant        none
// @run-at       document-end
// @license MIT
// ==/UserScript==
(function() {
  'use strict';
  const API_KEY = 'PUTYOURAPIHERE'; // put ur API in the ''
  const buyperc=.95 //prcentage of MV u wanna buy/sell at
  // item ids
  const cacheMap = {
    "Armor Cache": 1118,
    "Melee Cache": 1119,
    "Small Arms Cache": 1120,
    "Medium Arms Cache": 1121,
    "Heavy Arms Cache": 1122
  };
  // cache counter
  function extractCacheCounts(text) {
    const counts = {};
    Object.keys(cacheMap).forEach(cache => {
      const match = text.match(new RegExp(`(\\d+)x\\s+${cache}`));
      if (match) counts[cache] = parseInt(match[1], 10);
    });
    return counts;
  }
  // Fetch mvs
  async function fetchCacheMarketValues() {
    const resp = await fetch(`https://api.torn.com/torn/?selections=items&key=${API_KEY}`);
    if (!resp.ok) {
      alert(`API error: ${resp.status}`);
      return null;
    }
    const data = await resp.json();
    if (!data.items) {
      alert("API returned no items data.");
      return null;
    }
    // Extract cache mv
    const mvConstants = {};
    for (const cacheName in cacheMap) {
      const itemId = cacheMap[cacheName];
      mvConstants[itemId] = data.items[itemId]?.market_value || 0;
    }
    return mvConstants;
  }
  // calc tots
  function calculateTotals(counts, marketValues) {
    let total = 0;
    Object.entries(counts).forEach(([cache, count]) => {
      const mv = marketValues[cacheMap[cache]] || 0;
      total += mv * count;
    });
    return total;
  }
  // overlay and ui shit
  function createOverlay(id, label, value, topPos, rightPos) {//if you want to modify overlay stuff do it here, the `${}px` stuff has to be modified in the ovelay section
    const overlay = document.createElement('div');
    Object.assign(overlay, { id, className: 'cache-overlay' });
    Object.assign(overlay.style, {
      position: 'fixed',
      top: `${topPos}px`,
      right: `${rightPos}px`,
      backgroundColor: 'rgba(0, 0, 0, 0.7)',
      color: 'white',
      padding: '8px 12px',
      borderRadius: '4px',
      zIndex: '9999',
      fontSize: '14px',
      fontFamily: 'Arial, sans-serif',
      pointerEvents: 'none'
    });
    overlay.textContent = `${label}: $${value.toLocaleString()}`;
    document.body.appendChild(overlay);
  }
  function removeExistingOverlays() {//this resets overlays, mostly helps for debugging in console, you can probably cut this if u want
    document.querySelectorAll('.cache-overlay').forEach(el => el.remove());
  }
  function addCopyButton(value, topPos, width,right) {//if you want to modify button stuff do it here, the `${}px` stuff has to be modified in the ovelay section
    const button = document.createElement('button');
    Object.assign(button.style, {
      position: 'fixed',
      top: `${topPos}px`,
      right: `${right}px`,
      width:`${width}px`,
      height: '30px',
      backgroundColor: '#4CAF50',
      border: 'none',
      borderRadius: '4px',
      cursor: 'pointer',
      zIndex: '10000'
    });
    button.addEventListener('click', () => {
      const buyVal = Math.round(value * buyperc);//keep in mind that this is not actually taking the value of the thing its next to but instead first variable * buyperc
      const formatted = `$${buyVal.toLocaleString()}`;
      navigator.clipboard.writeText(formatted)
        .catch(err => console.error('Copy failed:', err));//idk what this shit is
    });
    document.body.appendChild(button);
  }
  function addTriggerButton() {//this posittions the trigger button
    const button = document.createElement('button');
    button.id = 'cacheTotalButton';
    button.textContent = 'Calculate Cache Totals';
    Object.assign(button.style, {
      position: 'fixed',
      top: '5px',
      right: '10px',
      padding: '10px 15px',
      backgroundColor: '#4CAF50',
      color: 'white',
      border: 'none',
      borderRadius: '4px',
      cursor: 'pointer',
      zIndex: '10000'
    });
    button.addEventListener('click', async () => {
      removeExistingOverlays();
      //this is a bunch id variables needed for displays, some of these are customizable
      const mvConstants = await fetchCacheMarketValues();
      if (!mvConstants) return; // Stop if API fetch failed
      const topText = document.querySelectorAll('.memberBonusRow___XJqsX')[0]?.innerText || '';
      const bottomText = document.querySelectorAll('.memberBonusRow___XJqsX')[1]?.innerText || '';
      const topCounts = extractCacheCounts(topText);
      const bottomCounts = extractCacheCounts(bottomText);
      const topTotal = calculateTotals(topCounts, mvConstants);
      const bottomTotal = calculateTotals(bottomCounts, mvConstants);
      const mv1118 = mvConstants[1118] || 0;
      const mv1119 = mvConstants[1119] || 0;
      const mv1120 = mvConstants[1120] || 0;
      const mv1121 = mvConstants[1121] || 0;
      const mv1122 = mvConstants[1122] || 0;
      if (topTotal === null || bottomTotal === null) return;
      const topBuy = Math.round(topTotal * buyperc);
      const bottomBuy = Math.round(bottomTotal * buyperc);
      //constants for qol. u dont HAVE to use these
      const opftr=80//overlay, pixels from top, right (this pushes the whole stack down)
      const opftl=5//overlay, pixels from top, left (this pushes the whole stack down)
      const sep=31//seperation distance btw overlays & buttons (all) make ur own l/r o/b things if you are that pedantic (or pay me 5m in torn to do it for you kek)
      const pfrtots=0//pixel from right for total overlays
      const pfrbuys=23//pixel from right buy overlays
      //overlay creation createOverlay(first part doesnt matter, text b4 value, value printed, pixels from top, pixels from right [nothing puts it all the way to the left])
      createOverlay('top-cache-overlay', 'Top Total', topTotal, opftr,pfrtots);
      createOverlay('bottom-cache-overlay', 'Bottom Total', bottomTotal, opftr+(sep*1),pfrtots);
      createOverlay('topbuy', 'Top Buy', topBuy, opftr+(sep*2),pfrbuys);
      createOverlay('bottombuy', 'Bottom Buy', bottomBuy, opftr+(sep*3),pfrbuys);
      createOverlay('',"Armor",mv1118,opftl);
      createOverlay('',"Melee",mv1119,opftl+(sep*1));
      createOverlay('',"Small",mv1120,opftl+(sep*2));
      createOverlay('',"Medium",mv1121,opftl+(sep*3));
      createOverlay('',"Heavy",mv1122,opftl+(sep*4));
      //constants for qol. u dont HAVE to use these
      const bpftr=80 //button, pixels from top, right (this pushes the whole stack down)
      const bpftl=5 //button, pixels from top, left (this pushes the whole stack down)
      const bwr=30 //button, width, right
      const bwl=10 //button, width, left
      // (value to * by buyperc, pixels from top, width, pixels from right)
      addCopyButton(topTotal,bpftr+(sep*2),bwr,0);
      addCopyButton(bottomTotal,bpftr+(sep*3),bwr,0);
      addCopyButton(mv1118,bpftl+(sep*0),bwl);// *0 is not needed here but whatevs
      addCopyButton(mv1119,bpftl+(sep*1),bwl);
      addCopyButton(mv1120,bpftl+(sep*2),bwl);
      addCopyButton(mv1121,bpftl+(sep*3),bwl);
      addCopyButton(mv1122,bpftl+(sep*4),bwl);
    });
    document.body.appendChild(button);
  }
  addTriggerButton();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址