See CodeChum hidden test cases

See hidden test cases as if they are not hidden in codechum after you press submit

当前为 2022-09-28 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         See CodeChum hidden test cases
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  See hidden test cases as if they are not hidden in codechum after you press submit
// @author       CIT Hackerz
// @match        https://citu.codechum.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=codechum.com
// @grant        none
// ==/UserScript==

const testCaseEndpoint = new RegExp('answers-v4\/[0-9]+\/executev2', 'g');

// Stylings
const style_testCaseContent = `display: grid; grid-row-gap: 16px; grid-template-column: minmax(0, 1fr); margin: 16px 0 8px;`;
const style_testCaseContent_title = `margin: 8px 0 12px;`;
const style_Text_n = `color: #b0b9bf;`;
const style_Text_heading = `font-family: Monsterrat,sans-serif; font-size: 1rem; line-height: 1.25; font-weight: 700; font-style: normal;`
const style_pre = `color: rgb(204, 204, 204); border-radius: 8px; background: rgb(45, 45, 45); font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; text-align: left; white-space: pre; word-spacing: normal; word-break: normal; overflow-wrap: normal; line-height: 1.5; tab-size: 4; hyphens: none; padding: 1em; margin: 0.5em 0px; overflow: auto;`;
const style_Code_sm = `background-color: #2d3845 !important;`
const style_code_el = `color: rgb(204, 204, 204); font-size: 14px; background: none; font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; text-align: left; white-space: pre; word-spacing: normal; word-break: normal; overflow-wrap: normal; line-height: 1.5; tab-size: 4; hyphens: none;`;

// Test Case template
const testCaseDiv = document.createElement("div");
testCaseDiv.innerHTML = `
<div style="${style_testCaseContent}">
    <div>
        <h6 style="${style_testCaseContent_title}${style_Text_n}${style_Text_heading}">
            Expected Output
        </h6>
        <div>
            <pre style='${style_pre}${style_Code_sm}'><code style='${style_code_el}'>
                    put test cases in here
                </code></pre>
        </div>
    </div>
</div>
`;

function event_displayHiddenCaseOnClick(e){
    // if next sibling (test case container) is hidden, then show, else hide
    const testCase = this.nextElementSibling;

    if(testCase.style.display != "block"){
        // show
        testCase.style.display = "block";
    }else{
        // hide
        testCase.style.display = "none";
    }

    console.log(testCase.style.display);
}

function displayCase(cases){

    // fucking obfuscation
    let testCaseCont = Array.from(document.querySelectorAll('div')).filter(e => e.classList.length > 0).filter(e => Array.from(e.classList).some(cl => cl.includes("styles_InputOutput_testCases")));

    // if there is a constraint, then the test case content is the second child
    testCaseCont = ((testCaseCont.length > 1) ? testCaseCont[1] : testCaseCont[0]).children[1];

    testCaseCont.children.forEach( (div, i) => {
        if(!div.children[0].disabled) return; // only modify hidden test cases

        const caseCont = testCaseDiv.cloneNode(true);
        caseCont.style.display = "none";

        caseCont.querySelector('code').innerHTML = cases[i].trim();

        // if div is not yet marked, add an event listener to the button
        if(div.dataset.marked != "true"){
            div.children[0].disabled = false;
            div.children[0].addEventListener("click", event_displayHiddenCaseOnClick);
            div.children[0].cursor = "pointer";
        }

        // set the div as marked
        div.dataset.marked = "true";

        div.append(caseCont);
    });
}

function saveCase(arg){
    let saved = sessionStorage.getItem("saved_test_cases") || [
        {
            problem: arg.id,
            cases: arg.cases
        }
    ];

    if(typeof saved == "string"){
        saved = JSON.parse(saved);
        saved.push({
           problem: arg.id,
            cases: arg.cases
        });
    }

    sessionStorage.setItem("saved_test_cases", JSON.stringify(saved));
}

function receiveCases(arg){
    let res;

    try {
        res = JSON.parse(arg.response);
    }catch (err){
        return;
    }

    const testCase = {
        id: res.id,
        answer_id: res.answer_id,
        cases: res.test_case_statuses.map(e => e.test_case.output)
    }

    displayCase(testCase.cases);
    //saveCase(testCase);
}

(function() {
    'use strict';

    // Modify open and send requests

    var open = window.XMLHttpRequest.prototype.open,
        send = window.XMLHttpRequest.prototype.send;

    function openReplacement(method, url, async, user, password) {
        this._url = url;
        return open.apply(this, arguments);
    }

    function sendReplacement(data) {
        if(this.onreadystatechange) {
            this._onreadystatechange = this.onreadystatechange;
        }

        // if you want to modify send requests

        this.onreadystatechange = onReadyStateChangeReplacement;
        return send.apply(this, arguments);
    }

    function onReadyStateChangeReplacement() {

        // modify here received requests
        if(testCaseEndpoint.test(this._url)) receiveCases(this);

        if(this._onreadystatechange) {
            return this._onreadystatechange.apply(this, arguments);
        }
    }

    window.XMLHttpRequest.prototype.open = openReplacement;
    window.XMLHttpRequest.prototype.send = sendReplacement;

    var request = new XMLHttpRequest();
    request.open('GET', '.', true);
    request.send();

})();