Show details about DC and RC upgrades
// ==UserScript==
// @name DeepCo Upgrades Helper V3.01
// @namespace https://deepco.app/
// @version 2025-10-25v3.01
// @description Show details about DC and RC upgrades
// @author Corns(original script), Zoltan (migrated to new architecture)
// @match https://deepco.app/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=deepco.app
// @license MIT
// @grant none
// ==/UserScript==
(function() {
'use strict';
const INTERVAL_MS = 1000;
new MutationObserver((mutation, observer) => {
const main = document.getElementById('main-panel');
if (main) { console.log('[Processing Page] Loaded');
observer.disconnect();
startLoop();
}
}).observe(document.body, { childList: true, subtree: true });
function startLoop() {
setInterval(() => {
getDeptnumber()
addButtonInfo();
}, INTERVAL_MS);
}
function getDeptnumber() {
// Find Dept value
const departmentLabel = document.querySelector('.select > option:nth-child(1)');
if (departmentLabel) {
const departmentLabel = document.querySelector('.select > option:nth-child(1)').innerHTML.split(' ', 2);
var departmentNumber = parseFloat(departmentLabel[0].replace(/[^0-9\.]+/g, '').trim());
localStorage.setItem("departmentNumber", departmentNumber);
}
}
function addButtonInfo() {
const mainPanel = document.querySelector('#grid-panel');
if (mainPanel) {
// Add Max PR to Department Tags
const departmentNumber = parseFloat(localStorage.getItem("departmentNumber"));
if (departmentNumber == 1) {
const departmentMaxPR = 125
localStorage.setItem("departmentMaxPR", departmentMaxPR);
let DCText = document.querySelector(`p[data-tag="Max PR"]`);
if (!DCText) {
DCText = document.createElement('p');
DCText.classList.add("font-semibold");
DCText.dataset.tag = 'Max PR';
document.querySelector(`.text-center`).appendChild(DCText);
}
DCText.textContent = `Department Max Rating = ${departmentMaxPR}`;
;
}
else if (departmentNumber > 1) {
const departmentMaxRating = (375 * ( 1.5 ** (departmentNumber - 3))).toFixed(2)
const departmentMaxPR = parseFloat(departmentMaxRating).toLocaleString('en')
localStorage.setItem("departmentMaxPR", departmentMaxRating);
let DCText = document.querySelector(`p[data-tag="Max PR"]`);
if (!DCText) {
DCText = document.createElement('p');
DCText.classList.add("font-semibold");
DCText.dataset.tag = 'Max PR';
document.querySelector(`.text-center`).appendChild(DCText);
}
DCText.textContent = `Department Max Rating = ${departmentMaxPR}`;
;
}
}
// Calculate DC needed to reach next Dept max rating and create label in side panel
let dcLabelText = document.querySelector(`#worker_coins > div:nth-child(1)`).querySelector(`p[data-tag="DC Needed"]`);
const departmentNumber = parseFloat(localStorage.getItem("departmentNumber"));
const deptMaxRating = localStorage.getItem("departmentMaxPR");
const ratingPerMax = localStorage.getItem("DCGainPerMaxLevel");
const currentRating = parseFloat(document.querySelector(`div.stat:nth-child(1) > span:nth-child(2)`).innerHTML);
const DCLevelsNeeded = Math.max(0, Math.floor((deptMaxRating - currentRating) / ratingPerMax));
const maxDCLevel = localStorage.getItem("maxPowerLevel");
const DCForMaxRating = Math.max(0, 5 * (DCLevelsNeeded - 1) * (DCLevelsNeeded + 2 * maxDCLevel -28)).toLocaleString('en');
if (!dcLabelText) {
dcLabelText = document.createElement('p');
dcLabelText.classList.add("text-sm");
dcLabelText.classList.add("font-semibold");
dcLabelText.classList.add("text-terminal-accent");
dcLabelText.dataset.tag = 'DC Needed';
document.querySelector(`#worker_coins > div:nth-child(1)`).appendChild(dcLabelText);
dcLabelText.textContent = `${DCForMaxRating} Total DC needed for DC+${departmentNumber} Max Rating`;
}
const dcFrame = document.querySelector('#deepcoin-upgrades');
if (!dcFrame) {
// console.log('[Upgrade] Upgrades panel not found.');
return;
}
const rcFrame = document.querySelector('#recursive-upgrades');
if (!rcFrame) {
// console.log('[Upgrade] Upgrades panel not found.');
return;
}
// Get base stats
const clockSpeed = Math.max(0.5, parseFloat(document.querySelector('[data-upgrade-type="dig_speed"] [class="flex-1"] > p:nth-child(2)').innerHTML));
const overclockChance = Math.min(0.1 , parseFloat(document.querySelector('[data-upgrade-type="crit_chance"] [class="flex-1"] > p:nth-child(2)').innerHTML) / 100);
const forkChance = Math.min(0.1 , parseFloat(document.querySelector('[data-upgrade-type="chain_chance"] [class="flex-1"] > p:nth-child(2)').innerHTML) / 100);
const minPower = parseFloat(document.querySelector('[data-upgrade-type="min_damage"] [class="flex-1"] > p:nth-child(2)').innerHTML);
const maxPower = parseFloat(document.querySelector('[data-upgrade-type="max_damage"] [class="flex-1"] > p:nth-child(2)').innerHTML);
const minBonusMatch = document.querySelector('article.shadow-md:nth-child(2) > div:nth-child(1) > div:nth-child(2) > span:nth-child(2)').innerHTML;
const maxBonusMatch = document.querySelector('article.shadow-md:nth-child(3) > div:nth-child(1) > div:nth-child(2) > span:nth-child(2)').innerHTML;
const totalBonusMatch = document.querySelector('article.shadow-md:nth-child(4) > div:nth-child(1) > div:nth-child(2) > span:nth-child(2)').innerHTML;
const dcYieldMatch = document.querySelector('article.shadow-md:nth-child(6) > div:nth-child(1) > div:nth-child(2) > span:nth-child(2)').innerHTML;
const minBonus = (parseFloat(minBonusMatch.replace(/[^0-9\.]+/g, '').trim()) + 100) / 100;
const maxBonus = (parseFloat(maxBonusMatch.replace(/[^0-9\.]+/g, '').trim()) + 100) / 100;
const totalBonus = (parseFloat(totalBonusMatch.replace(/[^0-9\.]+/g, '').trim()) + 100) /100;
const dcYield = parseFloat(dcYieldMatch.replace(/[^0-9\.]+/g, '').trim()) / 100;
// Math calculations
const avgPower = (minPower + maxPower) / 2;
const overclockMultiplier = 1 + overclockChance;
const forkMultiplier = 2 / (2 - forkChance);
const baseDPS = (avgPower / clockSpeed) * overclockMultiplier * forkMultiplier;
// Calculate DC max levels needed to reach next dept max rating
const maxPowerLevelMatch = document.querySelector('[data-upgrade-type="max_damage"] [class="flex-1"] > p:nth-child(2)').innerHTML.split(" ");
const maxPowerLevel = parseFloat(maxPowerLevelMatch[1].replace(/[^0-9\.]+/g, '').trim());
localStorage.setItem("maxPowerLevel", maxPowerLevel);
const departmentMaxPR = parseFloat(localStorage.getItem("departmentMaxPR"));
const DCGainPerMaxLevel = 4 * clockSpeed * maxBonus * totalBonus * (1 + overclockChance) / (2 - forkChance) ;
localStorage.setItem("DCGainPerMaxLevel", DCGainPerMaxLevel);
const MaxDCUpgradesNeeded = Math.max(0, Math.floor((departmentMaxPR - baseDPS) / DCGainPerMaxLevel));
// Create label for Max DC levels needed
let MaxDCLabel = dcFrame.querySelector('article.shadow-sm:nth-child(2) > div:nth-child(1) > header:nth-child(1) > div:nth-child(2)');
if (MaxDCLabel) {
let LabelText = MaxDCLabel.querySelector(`p[data-tag="Max Levels Needed"]`);
if (!LabelText) {
LabelText = document.createElement('p');
LabelText.classList.add("text-sm");
LabelText.classList.add("font-semibold");
LabelText.classList.add("text-terminal-accent");
LabelText.dataset.tag = 'Max Levels Needed';
MaxDCLabel.children[0].appendChild(LabelText);
LabelText.textContent = `${MaxDCUpgradesNeeded} Upgrades needed for next dept Max Rating`;
}
}
// update recursion protocol menu
const recursiveButtons = rcFrame.querySelectorAll('button');
recursiveButtons.forEach(button => {
if (!button.parentElement.parentElement.parentElement.children[1].children[0].innerHTML.includes('Cost:')) return;
const costMatch = button.parentElement.parentElement.parentElement.children[1].children[0].innerHTML.split(' ', 2);
if (!costMatch) return;
const rcCost = parseFloat(costMatch[1]);
// Make a copy of the current bonuses
const rawMinPower = (minPower / minBonus / totalBonus);
const rawMaxPower = (maxPower / maxBonus / totalBonus);
const basePower = (rawMinPower * minBonus + rawMaxPower * maxBonus) * totalBonus * overclockMultiplier * forkMultiplier;
let newMinBonus = minBonus;
let newMaxBonus = maxBonus;
let newTotalBonus = totalBonus;
let newDCYield = dcYield;
if (button.parentElement.parentElement.innerHTML.includes('/upgrade_recursive_min')) {
newMinBonus += 0.01;}
else if (button.parentElement.parentElement.innerHTML.includes('/upgrade_recursive_max')) {
newMaxBonus += 0.01;}
else if (button.parentElement.parentElement.innerHTML.includes('/upgrade_recursive_total_damage')) {
newTotalBonus += 0.01;}
else if (button.parentElement.parentElement.innerHTML.includes('/upgrade_recursive_dc_yield')) {
newDCYield += 0.01;}
const newAvgPower = (rawMinPower * newMinBonus + rawMaxPower * newMaxBonus) * newTotalBonus * overclockMultiplier * forkMultiplier;
const powerGain = newAvgPower - basePower;
const ratio = powerGain / rcCost;
const dcYieldPowerGain = 100 * (newDCYield / dcYield - 1);
const dcYieldratio = newAvgPower / (100 * newDCYield) / rcCost;
let RCText = button.parentElement.parentElement.querySelector(`span[data-tag="RC Upgrade Gain"]`);
if (!RCText) {
RCText = document.createElement('span');
RCText.classList.add("font-semibold");
RCText.dataset.tag = 'RC Upgrade Gain';
button.parentElement.parentElement.insertBefore(RCText, button.parentElement.nextSibling);}
if (button.parentElement.parentElement.innerHTML.includes('/upgrade_recursive_min')) {
RCText.textContent = `+${powerGain.toFixed(2)} PR (${1000 * ratio.toFixed(2)} RC Efficiency)`;}
else if (button.parentElement.parentElement.innerHTML.includes('/upgrade_recursive_max')) {
RCText.textContent = `+${powerGain.toFixed(2)} PR (${1000 * ratio.toFixed(2)} RC Efficiency)`;}
else if (button.parentElement.parentElement.innerHTML.includes('/upgrade_recursive_total_damage')) {
RCText.textContent = `+${powerGain.toFixed(2)} PR (${1000 * ratio.toFixed(2)} RC Efficiency)`;}
else if (button.parentElement.parentElement.innerHTML.includes('/upgrade_recursive_dc_yield')) {
RCText.textContent = `+${dcYieldPowerGain.toFixed(2)}% PR Gain (${1000 * dcYieldratio.toFixed(2)} RC Efficiency)`;}}
);
// Scan all upgrades
const DCButtons = dcFrame.querySelectorAll('#deepcoin-upgrades [class="p-2"]');
DCButtons.forEach(group => {
const buttons = group.querySelectorAll('[class="flex"]');
buttons.forEach(button => {
if (!button.textContent.includes('+1 ')) {
return;}
const match = button.textContent.match(/\+1.*\((\d+)\s*DC\)/);
if (!match) return;
const cost = parseInt(match[1], 10);
const isDisabled = button.disabled;
let newClockSpeed = clockSpeed;
let newMin = minPower;
let newMax = maxPower;
let newOverclockChance = overclockChance;
let newForkChance = forkChance;
if (button.action.includes('/upgrades/speed')) {
newClockSpeed = Math.max(0.5, clockSpeed - 0.1);}
else if (button.action.includes('/upgrades/min_damage')) {
const increase = 1 * minBonus * totalBonus;newMin += increase;}
else if (button.action.includes('/upgrades/damage')) {
const increase = 1 * maxBonus * totalBonus;newMax += increase;}
else if (button.action.includes('/upgrades/crit')) {
newOverclockChance += 0.01;}
else if (button.action.includes('/upgrades/chain')) {
newForkChance += 0.01;}
const newAvgPower = (newMin + newMax) / 2;
const newOverclockMultiplier = 1 + newOverclockChance;
const newForkMultiplier = 2 / (2 - newForkChance);
const newDPS =(newAvgPower / newClockSpeed) * newOverclockMultiplier * newForkMultiplier;
const dpsGain = newDPS - baseDPS;
const ratio = dpsGain / cost;
// add label to reflect new info
let DCText = button.parentElement.parentElement.parentElement.querySelector(`p[data-tag="DC Upgrade Gain"]`);
if (!DCText) {
DCText = document.createElement('p');
DCText.classList.add("text-sm");
DCText.classList.add("font-semibold");
DCText.classList.add("text-terminal-accent");
DCText.dataset.tag = 'DC Upgrade Gain';
button.parentElement.parentElement.parentElement.children[0].children[1].appendChild(DCText);
}
DCText.textContent = `+${dpsGain.toFixed(2)} Rating (${ratio.toFixed(2)} Rating/DC)`;}
);
});
}
})();