[Tool] Arealme - Color Hue Test

顯示所有方格的顏色順序。

目前為 2023-07-27 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         [Tool] Arealme - Color Hue Test
// @namespace    -
// @version      1.0
// @description  顯示所有方格的顏色順序。
// @author       LianSheng
// @match        https://www.arealme.com/color-hue-test/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=arealme.com
// @grant        none
// @license MIT
// ==/UserScript==

(function () {
    /**
     * 將文字格式 `rgb(r, g, b)` 轉成陣列 `[r, g, b]`.
     * @param {string} raw 
     * @returns {Array<number>}
     */
    function toRGB(raw) {
        raw = raw.replace("rgb(", "").replace(")", "");
        return raw.split(", ").map(Number);
    }

    /**
     * 選擇排序依據的色彩通道. 
     * @param {Array<number>} a `A[r, g, b]`
     * @param {Array<number>} b `B[r, g, b]`
     * @returns {number} Array index
     */
    function selectCriteriaChannel(a, b) {
        for (let i = 0; i <= 2; i++) {
            if (a[i] !== b[i]) {
                return i;
            }
        }
    }

    /**
     * 計算每個 box 的順序,並將其值附加至屬性 `ord`.
     * @param {Array<HTMLElement>} boxes 
     * @returns {void}
     */
    function sortBoxes(boxes) {
        const criteria = selectCriteriaChannel(
            toRGB(boxes[0].style.backgroundColor),
            toRGB(boxes[boxes.length - 1].style.backgroundColor)
        );

        const firstBox = boxes[0];

        boxes.sort((a, b) => toRGB(a.style.backgroundColor)[criteria] - toRGB(b.style.backgroundColor)[criteria]);

        if (boxes[0] !== firstBox) {
            boxes.reverse();
        }

        boxes.forEach((each, idx) => each.setAttribute("ord", idx + 1));
    }

    /**
     * 標記所有 box.
     * @param {Array<HTMLElement>} boxes 
     * @returns {void}
     */
    function markBoxes(boxes) {
        boxes.forEach(b => b.classList.add("modified"));
    }

    /**
     * 追加 [Show Hint] 按鈕到原本的打勾按鈕後面.
     * @returns {void}
     */
    function appendHintButton() {
        const confirm = document.querySelector(".dp-confirm-btn");
        const hint = document.createElement("button");
        hint.classList.add("show-hint");
        hint.style.backgroundColor = "red";
        hint.style.color = "black";
        hint.style.margin = "5em 1em";
        hint.style.padding = "6px 12px";
        hint.style.fontSize = "1.5rem";
        hint.style.fontWeight = "bold";
        hint.style.textShadow = "-1px 0 white, 0 1px white, 1px 0 white, 0 -1px white";
        hint.style.border = "4px solid #9999";

        hint.innerText = "Show Answer";

        hint.onclick = _ => {
            showHint();
            solveHandler();
        };

        confirm.insertAdjacentElement("afterend", hint);
        confirm.addEventListener("click", solveHandler);
    }

    /**
     * 在所有 box 上顯示答案.
     * @returns {void}
     */
    function showHint() {
        const boxes = [...document.querySelectorAll(".dp-box")];
        boxes.forEach(each => {
            each.innerText = each.getAttribute("ord");
            each.style.fontWeight = "bold";
            each.style.textShadow = "-1px 0 white, 0 1px white, 1px 0 white, 0 -1px white";
        });
    }

    /**
     * 主要程式
     * @returns {void}
     */
    function solveHandler() {
        const container = document.querySelector(".dp-box-container");

        if (container) {
            const boxes = [...document.querySelectorAll(".dp-box")];
            const hint = document.querySelector(".show-hint");

            if (boxes[0].classList.contains("modified")) {
                return;
            }

            if (!hint) {
                appendHintButton();
            }

            markBoxes(boxes);
            sortBoxes(boxes);

            return;
        }

        setTimeout(solveHandler, 100);
    }

    solveHandler();
})();