// ==UserScript== // @name 显示RW奖励价值 // @namespace http://tampermonkey.net/ // @version 1.4 // @description Show value of RW rewards. // @author bot_7420 [2937420] // @match https://www.torn.com/war.php?step=rankreport* // @run-at document-start // @grant GM.xmlHttpRequest // @connect api.torn.com // @downloadURL https://update.greasyfork.cloud/scripts/473564/%E6%98%BE%E7%A4%BARW%E5%A5%96%E5%8A%B1%E4%BB%B7%E5%80%BC.user.js // @updateURL https://update.greasyfork.cloud/scripts/473564/%E6%98%BE%E7%A4%BARW%E5%A5%96%E5%8A%B1%E4%BB%B7%E5%80%BC.meta.js // ==/UserScript== (function () { "use strict"; let API_KEY = localStorage.getItem("APIKey"); let marketValueMap = new Map(); let pointMarketValue = 0; const checkRows = async () => { const selectedElements = document.querySelectorAll("div.memberBonusRow___XJqsX"); if (selectedElements.length == 2) { console.log("RWAwardValue: found rows"); clearInterval(timer); await valueRow(selectedElements[0]); await valueRow(selectedElements[1]); } }; let timer = setInterval(checkRows, 200); async function valueRow(row) { let startingIndex = row.innerText.indexOf("bonus respect, ") + 15; let awardsString = row.innerText.substring(startingIndex, row.innerText.length); console.log("RWAwardValue: " + awardsString); let rowTotalValue = 0; let totalBB = 0; const backgroundColor = document.body.classList.contains("dark-mode") ? "#002800" : "#b5e7a0"; let appendInnerHTML = `
`; for (const item of awardsString.split(", ")) { if (item.includes("points")) { const pointValue = await valuePoint(); const numOfPoints = parseInt(item.substring(0, item.indexOf(" ")).replace(",", "")); rowTotalValue += pointValue * numOfPoints; const resultString = item + " (" + numberFormatter(pointValue) + " each)
"; appendInnerHTML += resultString; } else if (item.includes("Armor Cache")) { const cacheValue = await valueCache(1118); rowTotalValue += cacheValue * parseInt(item.substring(0, item.indexOf("x"))); totalBB += 60 * parseInt(item.substring(0, item.indexOf("x"))); const resultString = item + " (" + numberFormatter(cacheValue) + " each)
"; appendInnerHTML += resultString; } else if (item.includes("Melee Cache")) { const cacheValue = await valueCache(1119); rowTotalValue += cacheValue * parseInt(item.substring(0, item.indexOf("x"))); totalBB += 30 * parseInt(item.substring(0, item.indexOf("x"))); const resultString = item + " (" + numberFormatter(cacheValue) + " each)
"; appendInnerHTML += resultString; } else if (item.includes("Small Arms Cache")) { const cacheValue = await valueCache(1120); rowTotalValue += cacheValue * parseInt(item.substring(0, item.indexOf("x"))); totalBB += 20 * parseInt(item.substring(0, item.indexOf("x"))); const resultString = item + " (" + numberFormatter(cacheValue) + " each)
"; appendInnerHTML += resultString; } else if (item.includes("Medium Arms Cache")) { const cacheValue = await valueCache(1121); rowTotalValue += cacheValue * parseInt(item.substring(0, item.indexOf("x"))); totalBB += 50 * parseInt(item.substring(0, item.indexOf("x"))); const resultString = item + " (" + numberFormatter(cacheValue) + " each)
"; appendInnerHTML += resultString; } else if (item.includes("Heavy Arms Cache")) { const cacheValue = await valueCache(1122); rowTotalValue += cacheValue * parseInt(item.substring(0, item.indexOf("x"))); totalBB += 70 * parseInt(item.substring(0, item.indexOf("x"))); const resultString = item + " (" + numberFormatter(cacheValue) + " each)
"; appendInnerHTML += resultString; } } appendInnerHTML += "Total value: " + numberFormatter(rowTotalValue, 2) + " (" + totalBB + " Bunker Bucks)"; appendInnerHTML += `
`; row.innerHTML += appendInnerHTML; } function valueCache(itemId) { if (marketValueMap.has(itemId)) { return marketValueMap.get(itemId); } return new Promise((resolve, reject) => { GM.xmlHttpRequest({ url: `https://api.torn.com/torn/${itemId}?selections=items&key=${API_KEY}`, method: "POST", synchronous: true, onload: async (response) => { if (response.status == 200) { const body = JSON.parse(response.responseText); let marketValue = body.items[itemId].market_value; if (!marketValue || marketValue <= 0) { marketValue = await valueCacheBazaar(itemId); } marketValueMap.set(itemId, marketValue); resolve(marketValue); } else { console.error("RWAwardValue: valueCache API fetch onload with HTTP status " + response.status); resolve(0); } }, onabort: () => { console.error("RWAwardValue: valueCache API fetch onabort"); resolve(0); }, onerror: () => { console.error("RWAwardValue: valueCache API fetch onerror"); resolve(0); }, ontimeout: () => { console.error("RWAwardValue: valueCache API fetch ontimeout"); resolve(0); }, }); }); } function valueCacheBazaar(itemId) { return new Promise((resolve, reject) => { GM.xmlHttpRequest({ url: `https://api.torn.com/market/${itemId}?selections=bazaar&key=${API_KEY}`, method: "POST", synchronous: true, onload: (response) => { if (response.status == 200) { const body = JSON.parse(response.responseText); const bazaarValue = body.bazaar[0].cost; resolve(bazaarValue); } else { console.error("RWAwardValue: valueCacheBazaar API fetch onload with HTTP status " + response.status); resolve(0); } }, onabort: () => { console.error("RWAwardValue: valueCacheBazaar API fetch onabort"); resolve(0); }, onerror: () => { console.error("RWAwardValue: valueCacheBazaar API fetch onerror"); resolve(0); }, ontimeout: () => { console.error("RWAwardValue: valueCacheBazaar API fetch ontimeout"); resolve(0); }, }); }); } function valuePoint() { if (pointMarketValue > 0) { return pointMarketValue; } return new Promise((resolve, reject) => { GM.xmlHttpRequest({ url: `https://api.torn.com/market/?selections=pointsmarket&key=${API_KEY}`, method: "POST", synchronous: true, onload: (response) => { if (response.status == 200) { const body = JSON.parse(response.responseText); pointMarketValue = body.pointsmarket[Object.keys(body.pointsmarket)[1]].cost; resolve(pointMarketValue); } else { console.error("RWAwardValue: valuePoint API fetch onload with HTTP status " + response.status); resolve(0); } }, onabort: () => { console.error("RWAwardValue: valuePoint API fetch onabort"); resolve(0); }, onerror: () => { console.error("RWAwardValue: valuePoint API fetch onerror"); resolve(0); }, ontimeout: () => { console.error("RWAwardValue: valuePoint API fetch ontimeout"); resolve(0); }, }); }); } function numberFormatter(num, digits = 1) { const lookup = [ { value: 1, symbol: "" }, { value: 1e3, symbol: "k" }, { value: 1e6, symbol: "M" }, { value: 1e9, symbol: "B" }, ]; const rx = /\.0+$|(\.[0-9]*[1-9])0+$/; var item = lookup .slice() .reverse() .find(function (item) { return num >= item.value; }); return item ? (num / item.value).toFixed(digits).replace(rx, "$1") + item.symbol : "0"; } })();