Greasy Fork

[CS] Show Pet Rarity Count in Trades

Shows you how many pets of each rarity are in a trade.

// ==UserScript==
// @name        [CS] Show Pet Rarity Count in Trades
// @namespace   https://www.chickensmoothie.com/Forum/memberlist.php?mode=viewprofile&u=1123970
// @match       https://www.chickensmoothie.com/trades/edittrade.php*
// @match       https://www.chickensmoothie.com/trades/viewtrade.php*
// @description Shows you how many pets of each rarity are in a trade.
// @author      nuz
// @version     1.1
// @license     MIT
// @grant       GM_addStyle
// ==/UserScript==

/* jshint esversion: 11 */

const RARITY_EMOJI = {
  "unknown": "❔",
  "omgsocommon": "🔹",
  "extremelycommon": "🔷",
  "verycommon": "🔵",
  "common": "🟢",
  "uncommon": "💚",
  "veryuncommon": "💛",
  "extremelyuncommon": "🧡",
  "rare": "❤️",
  "veryrare": "💗",
  "extremelyrare": "💜",
  "omgsorare": "🌈",
};

const RARITIES = Object.keys(RARITY_EMOJI);

const RARITY_COUNT_CLASS = "rarity-count";
const RARITY_TOOLTIP_CLASS = "rarity-tooltip";
const RARITY_CONTAINER_CLASS = "rarity-container";

const TOOLTIP_FG_COLOR = "#111";
const TOOLTIP_BG_COLOR = "#eee";

const RARITY_COUNT_CSS = `
.petsection, .section.panel.bg4 {
  position: relative;
}

.petsection .${RARITY_COUNT_CLASS} {
  top: 2px;
}

.section.panel.bg4 .${RARITY_COUNT_CLASS} {
  top: 6px;
}

.${RARITY_COUNT_CLASS} {
  display: flex;
  position: absolute;
  right: 4px;
  font-size: 11px;
}

.${RARITY_COUNT_CLASS} > div {
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  min-width: 18px;
  padding: 0 6px;
  gap: 1px;
  cursor: help;
}

.${RARITY_COUNT_CLASS} > div:hover .${RARITY_TOOLTIP_CLASS} {
  opacity: 1;
}

.${RARITY_TOOLTIP_CLASS} {
  opacity: 0;
  transition: opacity 0.15s ease-in-out;
  position: absolute;
  top: calc(-100% - 3px);
  right: 50%;
  padding: 6px 10px;
  border-radius: 6px 6px 0 6px;
  text-align: center;
  white-space: nowrap;
  color: ${TOOLTIP_FG_COLOR};
  background-color: ${TOOLTIP_BG_COLOR};
}

.${RARITY_TOOLTIP_CLASS}::after {
  content: "";
  position: absolute;
  top: 100%;
  right: 0;
  border: 3px solid;
  border-color: ${TOOLTIP_BG_COLOR} ${TOOLTIP_BG_COLOR} #0000 #0000;
}

.cs-CSMobile .petsection.${RARITY_CONTAINER_CLASS} .${RARITY_COUNT_CLASS} {
  top: 50px;
}

.cs-CSMobile .petsection.${RARITY_CONTAINER_CLASS} .petbox {
  padding-top: 50px;
}

.cs-CSMobile .section.panel.bg4.${RARITY_CONTAINER_CLASS} {
  padding-top: 32px;
}

.cs-CSMobile .section.panel.bg4.${RARITY_CONTAINER_CLASS} .corners-top {
  transform: translateY(-32px);
}

.cs-CSMobile .${RARITY_COUNT_CLASS} > div {
  user-select: none;
}
`;

function updateRarityCount(petSection, attachElement) {
  const rarityMap = new Map();

  petSection.querySelectorAll(".pet").forEach((pet) => {
    const rarityMatch = pet
      .querySelector(".rarity-bar")
      ?.className.match(/ rarity-bar-(\w+) /)[1];
    const rarity = (!rarityMatch || rarityMatch === "stillgrowing") ?
      "unknown" : rarityMatch;

    rarityMap.set(rarity, (rarityMap.get(rarity) ?? 0) + 1);
  });
  petSection.querySelector(`.${RARITY_COUNT_CLASS}`)?.remove();

  if (!rarityMap.size) {
    petSection.classList.remove(RARITY_CONTAINER_CLASS);
    return;
  }

  const outerDiv = document.createElement("div");
  outerDiv.classList.add(RARITY_COUNT_CLASS);

  const entries = [...rarityMap.entries()].sort(
    (a, b) => RARITIES.indexOf(a[0]) - RARITIES.indexOf(b[0])
  );

  entries.forEach(([rarity, count]) => {
    const innerDiv = document.createElement("div");

    const tooltipText = rarity
      .replace(/^omgso/, "OMG so ")
      .replace(/^(extremely|very)/, "$& ")
      .replace(/^(\w)/, (match) => match.toUpperCase());

    [RARITY_EMOJI[rarity], count, tooltipText].forEach((text) => {
      const span = document.createElement("span");
      span.append(document.createTextNode(text));
      innerDiv.append(span);
    });

    innerDiv.lastElementChild.classList.add(RARITY_TOOLTIP_CLASS);
    outerDiv.append(innerDiv);
  });

  petSection.classList.add(RARITY_CONTAINER_CLASS);
  attachElement(outerDiv);
}

(function() {
  GM_addStyle(RARITY_COUNT_CSS);

  if (window.location.href.includes("viewtrade")) {
    document.querySelectorAll(".section.panel.bg4").forEach((section) => {
      updateRarityCount(section, (rarityCount) => {
        section.querySelector(".trade-things").before(rarityCount);
      });
    });
    return;
  }

  document.querySelectorAll(".petsection").forEach((section) => {
    const onMutate = () => {
      updateRarityCount(section, (rarityCount) => {
        section.append(rarityCount);
      });
    };
    onMutate(); // Initialize the rarity count.

    const petBox = section.querySelector(".petbox");
    new MutationObserver(onMutate).observe(petBox, {childList: true});
  });
})();