您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
See hidden test cases as if they are not hidden in codechum after you press submit
// ==UserScript== // @name See CodeChum hidden test cases // @namespace http://tampermonkey.net/ // @version 0.4 // @description See hidden test cases as if they are not hidden in codechum after you press submit // @author Lebron Samson // @match https://citu.codechum.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=codechum.com // @grant none // @license none // ==/UserScript== // url regex const testCaseEndpoint = new RegExp('answers-v4\/[0-9]+\/executev2', 'g'); const changeProblemEndPoints = [ "v3/page-visits/", "v3/answers-v4/", "v3/answer-comments/count/" ];0 // 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;`; // NEW STYLINGS const n_style_pre = `font-size: .875rem !important; font-style: normal; border-radius: 8px; margin: 0 !important; background-color: #2d3845 !important`; const n_style_code_h6 = `margin: 8px 0 12px !important`; const n_style_Text_heading = ` color: #b0b9bf; font-family: Montserrat,sans-serif; font-size: 1rem; line-height: 1.25; font-weight: 700; font-style: normal; margin: 0; `; // Test Case template const testCaseDiv = document.createElement("div"); testCaseDiv.classList.add("toBeHiddenIfClicked"); testCaseDiv.innerHTML = ` <div style="${style_testCaseContent} overflow-x: scroll;"> <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 getCodeDisplay(title, code){ const str = ` <h6 style='${n_style_code_h6}${n_style_Text_heading}'>${title}</h6> <div data-test="codeDiv"> <pre style='color: rgb(204, 204, 204); 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; ${n_style_pre}' ><code style='color: rgb(204, 204, 204); 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;'>${code}</code></pre> </div> `; const anotherSTR = ` <div style="${style_testCaseContent} overflow-x: auto;"> <div> <h6 style="${style_testCaseContent_title}${style_Text_n}${style_Text_heading}"> ${title} </h6> <div> <pre style='${style_pre}${style_Code_sm}'><code style='${style_code_el}'>${code}</code></pre> </div> </div> </div> `; const div = document.createElement("div"); div.classList.add("toBeHiddenIfClicked"); div.innerHTML = anotherSTR; return div; } function getDOM(targetCL, tag = "div"){ // fuck off obfuscation return Array.from(document.querySelectorAll(tag)).filter(e => e.classList.length > 0).filter(e => Array.from(e.classList).some(cl => cl.includes(targetCL))); } function getProblemName(){ return getDOM("Text", "h4")[0].innerText; } function event_displayHiddenCaseOnClick(e){ // if next sibling (test case container) is hidden, then show, else hide const tobeHidden = this.parentElement.getElementsByClassName("toBeHiddenIfClicked"); Array.from(tobeHidden).forEach(el => { el.style.display = (el.style.display != "block") ? "block" : "none"; }) } function event_displayCasesOnClick(e){ setTimeout(() => { tryToLoadCases("NOTHING"); }, 100); } function tryToLoadCases(arg){ const currProb = getProblemName(); console.log(currProb); // try to find the test case saved in the problem let saved = sessionStorage.getItem("saved_test_cases"); if(!saved) return; saved = JSON.parse(saved); const matches = saved.filter(e => e.problem == currProb); console.log(matches); if(matches.length){ displayCase(matches[0].cases, matches[0].actuals); } } function displayCase(cases, actuals = []){ let testCaseCont = getDOM("testCases")[0]; console.log("Testcases:", testCaseCont); if(testCaseCont.length && testCaseCont.length == 0 || cases.length == 0) return; try{ testCaseCont = testCaseCont.children[1]; }catch{ return; } // if there is a constraint, then the test case content is the second child // testCaseCont = ((testCaseCont.length && testCaseCont.length > 1) ? testCaseCont[1] : testCaseCont[0]).children[1]; Array.from(testCaseCont.children).forEach( (div, i) => { div = div.children[0]; console.log(div); if(!div.children[0].disabled) return; // only modify hidden test cases const expected = getCodeDisplay("ExpectedOutput", cases[i].trim()); const actual = getCodeDisplay("Your Output", actuals[i]?.trim()); expected.style.display = "none"; actual.style.display = "none"; // 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].style.cursor = "pointer"; } // set the div as marked div.dataset.marked = "true"; div.append(actual, expected); // div.children[1].style.display = "none"; console.log("TEST"); }); } function saveCase(arg){ const prob = getProblemName(); let saved = sessionStorage.getItem("saved_test_cases") || [ { problem: prob, cases: arg.cases } ]; if(typeof saved == "string"){ saved = JSON.parse(saved); // check if problem is already saved, if not then save if(!saved.some(e => e.problem == prob)) { saved.push({ problem: prob, cases: arg.cases, actuals: arg.actuals }); } } sessionStorage.setItem("saved_test_cases", JSON.stringify(saved)); } var shouldLoadCases = false, flag_changeProblem = [0, 0, 0]; function receiveCases(arg){ let res; console.log("YOU SUBMITTED"); try { res = JSON.parse(arg.response); }catch (err){ return; } if(!res.test_case_statuses) return; const testCase = { id: res.id, answer_id: res.answer_id, actuals: res.test_case_statuses.map(e => e.actual_output), cases: res.test_case_statuses.map(e => e.test_case.output) } if(!this.firstRun){ this.firstRun = 1; // the first ever submit, add event listener to test cases button and change problem button const test_case_button = document.querySelector("#testsTab"); const change_problem_button = getDOM("navigation_nav", "div")[0].querySelectorAll(`button`); console.log(change_problem_button); test_case_button.addEventListener("click", event_displayCasesOnClick); change_problem_button.forEach(e => e.addEventListener("click", function(){ shouldLoadCases = true; })); } displayCase(testCase.cases, testCase.actuals); 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 // for submitting if(testCaseEndpoint.test(this._url)) receiveCases(this); // for changing problems else if(changeProblemEndPoints.some(e => this._url.includes(e)) && shouldLoadCases){ flag_changeProblem[changeProblemEndPoints.findIndex(e => this._url.includes(e))]++; if(flag_changeProblem.every(e => e == 3)){ console.log("YOU CHANGED TABS!!!!!!!!!!!"); tryToLoadCases(this); shouldLoadCases = false; flag_changeProblem = [0, 0, 0]; } } 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(); })();