Price per TB Calculator & Sorter

Calculates price per TB, sorts products by value, and applies a color gradient.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Price per TB Calculator & Sorter
// @namespace    https://greasyfork.org/en/users/1019658-aayush-dutt// @version      1.0
// @description  Calculates price per TB, sorts products by value, and applies a color gradient.
// @author       aayushdutt
// @match        https://www.primeabgb.com/*
// @grant        none
// @license      MIT
// @version      1.0
// ==/UserScript==

(function() {
    'use strict';

    // --- CONFIGURATION ---
    // Adjust these values to tweak the color gradient logic.
    const CONFIG = {
        currencySymbol: '₹',
        medianPrice: 2500, // The price point considered "average" (yellow).
        gradientRange: 2000  // The range around the median for the full gradient.
    };

    /**
     * Calculates a darker, high-contrast color based on the price per TB.
     * @param {number} price - The price per terabyte.
     * @returns {string} An RGB color string (e.g., 'rgb(200, 0, 0)').
     */
    function getColorForPrice(price) {
        const normalized = (price - CONFIG.medianPrice) / CONFIG.gradientRange;
        const clamped = Math.max(-1, Math.min(1, normalized));

        let r, g;
        if (clamped < 0) { // Gradient from Dark Green to Dark Yellow
            r = 200 * (1 + clamped);
            g = 150;
        } else { // Gradient from Dark Yellow to Dark Red
            r = 200;
            g = 150 * (1 - clamped);
        }
        return `rgb(${Math.round(r)}, ${Math.round(g)}, 0)`;
    }

    /**
     * Parses a product element to extract its title, price, and storage capacity.
     * @param {HTMLElement} productEl - The product's container element.
     * @returns {object|null} An object with product data or null if essential data is missing.
     */
    function parseProductData(productEl) {
        const titleElement = productEl.querySelector('.product-title a');
        const priceElement = productEl.querySelector('.price ins .woocommerce-Price-amount.amount bdi');

        if (!titleElement || !priceElement) return null;

        const title = titleElement.innerText;
        const tbMatch = title.match(/(\d+)\s*TB/i);

        if (!tbMatch) return null;

        const terabytes = parseInt(tbMatch[1], 10);
        const priceText = priceElement.innerText.replace(new RegExp(`[${CONFIG.currencySymbol},]`, 'g'), '');
        const price = parseFloat(priceText);

        if (isNaN(price) || isNaN(terabytes) || terabytes <= 0) return null;

        const pricePerTb = price / terabytes;
        return { element: productEl, pricePerTb };
    }

    /**
     * Creates and injects the price-per-TB element into the DOM.
     * @param {object} productData - The object returned from parseProductData.
     */
    function injectPriceDisplay(productData) {
        if (!productData) return;

        // Remove old element if the script is re-run
        const oldDisplay = productData.element.querySelector('.price-per-tb');
        if (oldDisplay) oldDisplay.remove();

        const displayEl = document.createElement('div');
        displayEl.className = 'price-per-tb';
        displayEl.innerText = `${CONFIG.currencySymbol}${productData.pricePerTb.toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} / TB`;

        // Apply styles
        displayEl.style.fontSize = '14px';
        displayEl.style.fontWeight = 'bold';
        displayEl.style.color = getColorForPrice(productData.pricePerTb);
        displayEl.style.marginTop = '5px';

        const priceContainer = productData.element.querySelector('.product-price');
        if (priceContainer) {
            priceContainer.appendChild(displayEl);
        }
    }

    /**
     * Main function to orchestrate the script's execution.
     */
    function main() {
        const productContainer = document.querySelector('.products.products-wrap');
        if (!productContainer) {
            console.error("PricePerTB Script: Product container not found.");
            return;
        }

        const products = Array.from(productContainer.querySelectorAll('.product.type-product'));

        const productsData = products.map(parseProductData).filter(Boolean);

        // Inject the price display for each valid product.
        productsData.forEach(injectPriceDisplay);

        // Sort the products based on price per TB (lowest to highest).
        productsData.sort((a, b) => a.pricePerTb - b.pricePerTb);

        // Re-append the sorted elements into the container.
        productsData.forEach(item => {
            productContainer.appendChild(item.element);
        });
    }

    // Run the script.
    main();

})();