DeepCo Upgrades Helper V3.01

Show details about DC and RC upgrades

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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)`;}
      );
    });
  }
})();