Codeforces Modern Design

A modern UI redesign for Codeforces platform

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         Codeforces Modern Design
// @name:en      Codeforces Modern Design
// @namespace    https://github.com/funcdfs
// @version      1.2
// @description  A modern UI redesign for Codeforces platform
// @description:en  A modern UI redesign for Codeforces platform
// @description:zh-CN  Codeforces 平台的现代化界面重设计
// @author       funcdfs
// @match        https://atcoder.jp/contests/*
// @match        https://codeforces.com/*/problem/*
// @match        https://codeforces.com/contest/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=codeforces.com
// @grant        none
// @license MIT
// ==/UserScript==

(function () {
    'use strict';
    const codeforces_css = () => {
        const styleTag = document.createElement('style');
        const cssRules = `
pre {
    font-family:  source code pro;
}
div.ttypography tbody td {
    text-align: left;
    border-top: 0px solid #ccc;
}
body {
    background-color: #e7e9ed0f;
}
.roundbox-lt,
.roundbox-rt,
.roundbox-lb,
.roundbox-rb {
    display: none;
}
.roundbox {
    padding-bottom: 10px;
    border-radius: 10px;
}
.sidebox.roundbox {
    margin-top: 10px;
}
.menu-box {
    margin-top: 0px !important;
    -webkit-transition: none !important;
    -moz-transition: none !important;
    -ms-transition: none !important;
    -o-transition: none !important;
    transition: none !important;
}
.menu-box:hover {
    -webkit-box-shadow: none !important;
    -moz-box-shadow: none !important;
    box-shadow: none !important;
}
/** Custom sidebar */
.roundbox {
    margin-top: 10px;
    border: none;
    -webkit-transition: all 0.3s linear 0s;
    -moz-transition: all 0.3s linear 0s;
    -ms-transition: all 0.3s linear 0s;
    -o-transition: all 0.3s linear 0s;
    transition: all 0.3s linear 0s;
}
.roundbox:hover {
    -webkit-box-shadow: 0 1px 15px 0 rgba(0, 0, 0, 0.1);
    -moz-box-shadow: 0 1px 15px 0 rgba(0, 0, 0, 0.1);
    box-shadow: 0 1px 15px 0 rgba(0, 0, 0, 0.1);
}
.roundbox .titled {
    padding: 10px;
    border-bottom-color: #e4e6eb;
}
.sidebox div {
    border-bottom-color: #e4e6eb !important;
}

/** Sidebar avatar custom */
.personal-sidebar .for-avatar {
    float: none !important;
    display: block;
    font-size: 18px;
    padding: 10px;
}

.personal-sidebar .for-avatar .avatar img {
    border-radius: 50px;
    width: 90px;
    height: 90px;
    object-fit: cover;
}

/** Sidebar remove property links*/
.personal-sidebar .propertyLinks {
    display: none;
}

.personal-sidebar .nav-links {
    border-top-style: solid;
    border-top-width: 1px;
    border-top-color: #e4e6eb;
    padding-top: 10px;
}

.personal-sidebar .nav-links li {
    list-style-type: none !important;
    padding: 10px;
    font-size: 13px;
    border-radius: 5px;
    -webkit-transition: all 0.2s linear 0s;
    -moz-transition: all 0.2s linear 0s;
    -ms-transition: all 0.2s linear 0s;
    -o-transition: all 0.2s linear 0s;
    transition: all 0.2s linear 0s;
}

.personal-sidebar .nav-links li a,
.personal-sidebar .nav-links li a:visited {
    color: #050505;
}

.personal-sidebar .nav-links li:after {
    content: '→';
    float: right;
    color: #050505;
}

.personal-sidebar .nav-links li:hover {
    background-color: rgba(0, 0, 0, 0.05);
}

.personal-sidebar .nav-links li a {
    text-decoration: none !important;
}

.roundbox .bottom-links {
    padding: 10px;
    background-color: #fff;
    border-top-color: #e4e6eb !important;
    border-bottom-left-radius: 10px !important;
    border-bottom-right-radius: 10px !important;
}

.roundbox .rtable .dark {
    background-color: #fff;
}
/** Topic custom */
.topic {
    margin-top: 10px;
    padding: 20px;
    background-color: #fff;
    border-radius: 10px;
    -webkit-transition: all 0.3s linear 0s;
    -moz-transition: all 0.3s linear 0s;
    -ms-transition: all 0.3s linear 0s;
    -o-transition: all 0.3s linear 0s;
    transition: all 0.3s linear 0s;
}

.topic:hover {
    -webkit-box-shadow: 0px 1px 15px 0px rgba(0, 0, 0, 0.1);
    -moz-box-shadow: 0px 1px 15px 0px rgba(0, 0, 0, 0.1);
    box-shadow: 0px 1px 15px 0px rgba(0, 0, 0, 0.1);
}

.topic .roundbox {
    border-style: solid;
    border-color: #e4e6eb;
}

.topic .meta a {
    text-decoration: none;
}

.meta {
    padding-bottom: 0px !important;
}

.topic .content {
    border-left-color: #e4e6eb;
}
.roundbox .rtable td,
.roundbox .rtable th {
    border-bottom: 1px solid #e4e6eb;
    border-left: none;
    padding: 7px;
}

/** Header custom */
#header {
    padding: 20px;
    margin-top: -14px;
    background-color: #fff;
}

.menu-box {
    padding: 10px;
    border-radius: 0;
    border-top: none;
    border-left: none;
    border-right: none;
    border-bottom-left-radius: 20px;
    border-bottom-right-radius: 20px;
    border-bottom-color: #e4e6eb;
}

/** Footer custom */
#footer {
    background-color: #fff;
    width: 100%;
    height: 100%;
    border-top-left-radius: 20px;
    border-top-right-radius: 20px;
    border-top-color: #e4e6eb;
}

/** Contest data table */
.datatable .lt,
.datatable .rt,
.datatable .lb,
.datatable .rb,
.datatable .ilt,
.datatable .irt {
    display: none;
}

.datatable table {
    margin-top: 10px;
    border-style: solid;
    border-color: #e4e6eb;
    border-width: 1px;
}

.datatable table .dark {
    background-color: #fff;
}

.datatable table td {
    padding-top: 5px;
    padding-bottom: 5px;
    padding-left: 10px;
    padding-right: 10px;
}

.datatable {
    padding: 20px !important;
    width: inherit;
    padding-bottom: 40px !important;
    background-color: #fff !important;
    border-radius: 10px;
    -webkit-transition: all 0.3s linear 0s;
    -moz-transition: all 0.3s linear 0s;
    -ms-transition: all 0.3s linear 0s;
    -o-transition: all 0.3s linear 0s;
    transition: all 0.3s linear 0s;
}

.datatable:hover {
    -webkit-box-shadow: 0px 1px 15px 0px rgba(0, 0, 0, 0.1);
    -moz-box-shadow: 0px 1px 15px 0px rgba(0, 0, 0, 0.1);
    box-shadow: 0px 1px 15px 0px rgba(0, 0, 0, 0.1);
}

.contests-table::first-line {
    font-size: 20px;
    font-weight: bold !important;
}


.datatable {
    margin-top: 10px !important;
}

/** Custom input */
input[type="file"] {
    padding: 2px 2px!important;
    border: none !important;
}

input,
button {
    outline: none;
    height: auto !important;
    padding: 5px 30px 5px 30px !important;
    border-radius: 10px;
    border-width: 1.5px;
    border-color: #3b5998;
    font-weight: normal;
    -webkit-transition: all 0.3s linear 0s;
    -moz-transition: all 0.3s linear 0s;
    -ms-transition: all 0.3s linear 0s;
    -o-transition: all 0.3s linear 0s;
    transition: all 0.3s linear 0s;
}

input:hover,
button:hover {
    color: rgba(0, 0, 0, 0.7);
    background-color: #e4e6eb;
}

label[for=searchByProblemCheckbox] {
    margin-top: 20px !important;
    color: rgba(0, 0, 0, 0.5);
}

.notice {
    margin-top: 10px !important;
}

.highlighted-row td,
.highlighted-row th {
    background-color: rgba(221, 238, 255, 0.47) !important;
}

input[name=sourceFile] {
    border-style: dashed;
    border-width: 2px;
    border-color: #e4e6eb;
    border-radius: 10px;
    padding: 5px;
    width: 100%;
}

.submit-form {
    margin-top: 20px;
    background-color: #fff;
    padding: 20px 0 20px 0;
    border-radius: 10px;
    -webkit-transition: all 0.3s linear 0s;
    -moz-transition: all 0.3s linear 0s;
    -ms-transition: all 0.3s linear 0s;
    -o-transition: all 0.3s linear 0s;
    transition: all 0.3s linear 0s;
}

.submit-form:hover {
    -webkit-box-shadow: 0px 1px 15px 0px rgba(0, 0, 0, 0.1);
    -moz-box-shadow: 0px 1px 15px 0px rgba(0, 0, 0, 0.1);
    box-shadow: 0px 1px 15px 0px rgba(0, 0, 0, 0.1);
}

.source-popup pre {
    padding: 10px;
    border-style: solid;
    border-width: 2px;
    border-color: #e4e6eb;
}

hr {
    border: 0;
    height: 2px;
    background-image: linear-gradient(to right, rgba(228, 230, 235, 0.1), rgba(228, 230, 235, 1), rgba(228, 230, 235, 0.1));
}

.popup-input-div div,
.popup-output-div div,
.popup-answer-div div,
.popup-checker-div div {
    margin-top: 10px;
    margin-bottom: 5px;
}

.table-form {
    padding: 10px;
}
.diff-notifier {
    display: none !important;
}
/*main*/
.problemindexholder {
    box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
    margin-top: 10px;
    background-color: #fff;
    padding: 30px;
    border-radius: 10px;
    -webkit-transition: all 0.3s linear 0s;
    -moz-transition: all 0.3s linear 0s;
    -ms-transition: all 0.3s linear 0s;
    -o-transition: all 0.3s linear 0s;
    transition: all 0.3s linear 0s;
}

.sample-test {
    margin-top: 10px;
}

.sample-test .input .title,
.sample-test .output .title {
    font-size: 15px;
}

.sample-test pre {
    padding-top: 10px !important;
    padding-bottom: 10px !important;
    padding-left: 5px !important;
    padding-right: 5px !important;
}

.placeholder {
    margin-bottom: 10px !important;
}

a[href^="/passwordRecovery"] {
    display: block;
    margin-top: 20px !important;
}

.backLava {
    border-radius: 10px;
}

#body {
    max-width: 1220px;
    min-width: 980px;
}

::selection {
    background-color: #c4b5fd!important;
    color: #000!important;
}

::-webkit-scrollbar-thumb {
    background: #323536!important;
}
::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}
div.ttypography a:hover {
    color: #9e88f5 !important;
    background: #cfecdc;
}
div.ttypography li,
div.ttypography p {
    font-size: 1.1em;
    line-height: 1.4em;
}
/** Footer custom */
#footer {
    /** background-color: #fff;
    width: 100%;
    height: 100%;
    border-top-left-radius: 20px;
    border-top-right-radius: 20px;
    border-top-color: #e4e6eb;
    **/
    display: none !important;
}
pre {
    tab-size: 4;
}
.sidebar-menu ul {
    font-size: 1.4rem;
}
body {
    zoom: 111% !important;
}
/** move pos, if you want the pos, just delete below string **/
#header {
    position: absolute !important;
    top: 20px;
    z-index: 1;
    right: 20px;
    /* 将元素右对齐 */
    width: 220px;
    background: #00000000;
}
.menu-box {
    background: #00000000;
    width: 70%;
}
.property-title,
#header > div:nth-child(1) {
    display: none !important;
}
/** info remove to bottom */
.time-limit {
    position: fixed !important;
    right: 30px;
    bottom: 70px;
    z-index: 9;
}
.memory-limit {
    position: fixed !important;
    right: 30px;
    bottom: 50px;
    z-index: 9;

}
.input-file {
    position: fixed !important;
    right: 30px;
    bottom: 30px;
    z-index: 9;
}
.output-file {
    position: fixed !important;
    right: 30px;
    bottom: 10px;
    z-index: 9;
}
`;
        styleTag.appendChild(document.createTextNode(cssRules));
        document.head.appendChild(styleTag);
    };
    const codeforces_luogu = () => {
        function getProblemId(str) {
            let pos = str.indexOf("contest/") + "contest/".length;
            let contestNum = "";
            while (str[pos] >= '0' && str[pos] <= '9') {
                contestNum += str[pos];
                pos++;
            }
            return contestNum;
        }
        function getProblemChar(str) {
            let pos = str.indexOf("problem/") + "problem/".length;
            let problemLetter = str.substr(pos);
            return problemLetter;
        }
        // jump to luogu.com 跳转到洛谷 delete luogu
        let str = window.location.href
        let problemId = getProblemId(str);
        let problemChar = getProblemChar(str);
        let luogulink = document.createElement('li');
        luogulink.setAttribute('style', 'color: green !important;');
        luogulink.innerHTML = `<a href="https://www.luogu.com.cn/problem/CF${problemId}${problemChar}" target="_blank"> 洛谷 </a>`;
        luogulink.classList.add('luogulink')
        document.querySelector("#sidebar > div.roundbox.sidebox.sidebar-menu.borderTopRound > ul").appendChild(luogulink)
    };
    const codeforces_friend_status = () => {
        // friends-status-button 好友提交历史记录
        let uuuuuuuuurl = window.location;
        let cccontestId = uuuuuuuuurl.toString().split("/").filter((x) => {
            if (typeof x !== 'string') { return; }
            const num = Number(x);
            if (Number.isInteger(num)) { return num; }
        })[0];
        let s = uuuuuuuuurl.toString().split("/");
        let iiid = s[s.length - 1];
        let friendBtn = document.createElement('li');
        friendBtn.innerHTML = `<a href="https://codeforces.com/contest/${cccontestId}/status/${iiid}?friends=on" target="_blank">Friends Status</a>`;
        friendBtn.classList.add('friendBtn')
        document.querySelector(".second-level-menu-list").appendChild(friendBtn);
    };
    const codeforces_timeLimits = () => {
        // time limits part 时间限制等 放到一个位置
        /* const timeLimits = document.querySelector(".time-limit");
        const memoryLimits = document.querySelector(".memory-limit");
        const inputLimits = document.querySelector(".input-file");
        const outputLimits = document.querySelector(".output-file");
        let informationSpace = document.querySelector();
        informationSpace.parentNode.insertBefore(informationSpace, info); */
        //informationSpace.appendChild(timeLimits);
        //informationSpace.appendChild(memoryLimits);
        //informationSpace.appendChild(inputLimits);
        //informationSpace.appendChild(outputLimits);
    };
    const KEY_PREFIX = 'funcdfs';
    const atcoder_navigation = () => {
        const contest = location.href.match(/^https:\/\/atcoder\.jp\/contests\/([^\/?]+)/)[1];
        const key = KEY_PREFIX + 'atcoder-' + contest;
        if (location.href.match(/^https:\/\/atcoder\.jp\/contests\/([^\/]+)\/tasks\/?$/)) {
            const problems = [];
            const rows = document.querySelectorAll('tbody>tr');
            for (let i = 0; i < rows.length; i++) {
                const links = rows[i].querySelectorAll('a');
                const href = links[0].getAttribute('href');
                const text = links[0].textContent + ' - ' + links[1].textContent;
                problems.push({
                    href: href,
                    text: text
                });
            }
            localStorage[key] = JSON.stringify(problems);
        }
        if (key in localStorage) {
            let problems = JSON.parse(localStorage[key]);
            const problemsBar = document.createElement('ul');
            problemsBar.className = 'nav nav-tabs';
            for (let i = 0; i < problems.length; i++) {
                const link = document.createElement('a');
                link.setAttribute('style', 'margin-left: 10px; margin-right: 10px; white-space: nowrap');
                link.setAttribute('href', problems[i].href);
                link.textContent = problems[i].text;
                const span = document.createElement('span');
                span.textContent = ' ';
                span.appendChild(link);
                problemsBar.appendChild(span);
            }
            document.getElementById('contest-nav-tabs').appendChild(problemsBar);
        }
    };
    const codeforces_navigation = () => {
        const contest = location.href.match(/^https:\/\/codeforces\.com\/contest\/([^\/?]+)/)[1];
        const key = KEY_PREFIX + 'codeforces-' + contest;
        if (location.href.match(/^https:\/\/codeforces\.com\/contest\/([^\/]+)\/?$/)) {
            const problems = [];
            const rows = document.querySelectorAll('.problems>tbody>tr');
            for (let i = 1; i < rows.length; i++) {
                const links = rows[i].querySelectorAll('a');
                const href = links[0].getAttribute('href');
                const text = links[0].textContent.trim() + '. ' + links[1].textContent;
                problems.push({
                    href: href,
                    text: text
                });
            }
            localStorage[key] = JSON.stringify(problems);
        }

        if (key in localStorage) {
            let problems = JSON.parse(localStorage[key]);
            const problemsBar = document.createElement('ul');
            problemsBar.setAttribute('style', 'margin-left: 15px; margin-right: 280px; padding-top: 30px');
            for (let i = 0; i < problems.length; i++) {
                const link = document.createElement('a');
                link.setAttribute('style', 'margin-right: 20px; white-space: nowrap');
                link.setAttribute('href', problems[i].href);
                link.textContent = problems[i].text;
                const span = document.createElement('span');
                span.textContent = ' ';
                span.appendChild(link);
                problemsBar.appendChild(span);
            }

            const content = document.getElementById('pageContent');
            content.parentNode.insertBefore(problemsBar, content);
        }
    };
    if (location.href.match(/^https:\/\/atcoder\.jp\/contests\//)) {
        atcoder_navigation();
    } else {
        if (location.href.match(/^https:\/\/codeforces\.com\/contest\//)) {
            codeforces_navigation();
        }
        codeforces_css();
        codeforces_luogu();
        codeforces_friend_status();
        codeforces_timeLimits();
    }
})();