codeforces-problem-queue

You can queue the problems you want to revenge!

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         codeforces-problem-queue
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  You can queue the problems you want to revenge!
// @author       itohdak
// @license      MIT
// @match        https://codeforces.com/contest/*/problem/*
// @match        https://codeforces.com/profile/*
// @grant        none
// ==/UserScript==

var max_problem_count = 50;
function getProblemQueue () {
    return JSON.parse(localStorage.getItem('problemQueue') || '{}');
}
function setProblemQueue (problemQueue) {
    localStorage.setItem('problemQueue', JSON.stringify(problemQueue));
}
function addProblem (problemTitle, problemContent) {
    var problemQueue = getProblemQueue();
    if(problemTitle in problemQueue) {
        return "Already in queue.";
    } else if(Object.keys(problemQueue).length >= max_problem_count) {
        return "Reached the maximum number of problems you can queue.</br>Let\'s solve the problems!:)";
    } else {
        problemQueue[problemTitle] = problemContent;
        setProblemQueue(problemQueue);
        return "Added successfully.";
    }
}
function deleteProblem (problemTitle) {
    var problemQueue = getProblemQueue();
    delete problemQueue[problemTitle];
    setProblemQueue(problemQueue);
}

function setAddProblemButton () {
    // Create a button in a container div.
    var div = document.createElement('div');
    div.setAttribute('style', 'margin:1em;font-size:0.8em;');
    div.setAttribute('id', 'addProblemContainer');
    var btn = document.createElement('input');
    btn.setAttribute('type', 'submit');
    btn.setAttribute('value', 'Add this problem to my problem queue');
    btn.setAttribute('style', 'padding:0 0.5em;');
    btn.setAttribute('id', 'addProblemButton');
    div.appendChild(btn);
    document.getElementsByClassName('header')[0].appendChild(div);

    // Activate the newly added button.
    document.getElementById('addProblemButton').addEventListener(
        'click', buttonClickAction, false
    );
}

function buttonClickAction (event) {
    var problemTitle = document.getElementsByClassName('title')[0].innerHTML
    var contestName = document.getElementsByClassName('left')[0].querySelectorAll('a')[0].text
    var msg = addProblem(problemTitle, {'contestName': contestName, 'problemLink': location.href});

    var p = document.createElement('p');
    p.innerHTML = '<font color="red">' + msg + '</font>';
    var cntr = document.getElementById('addProblemContainer');
    if(cntr.children.length > 1) cntr.removeChild(cntr.childNodes[1]);
    cntr.appendChild(p);
}

function createCodeforcesLikeRoundBox () {
    var roundBox = document.createElement('div');
    roundBox.setAttribute('class', 'roundbox sidebox top-contributed');
    roundBox.setAttribute('style', 'margin-top:1em;');
    var roundBoxLT = document.createElement('div');
    roundBoxLT.setAttribute('class', 'roundbox-lt');
    roundBoxLT.innerHTML = '&nbsp;';
    var roundBoxRT = document.createElement('div');
    roundBoxRT.setAttribute('class', 'roundbox-rt');
    roundBoxRT.innerHTML = '&nbsp;';
    var roundBoxLB = document.createElement('div');
    roundBoxLB.setAttribute('class', 'roundbox-lb');
    roundBoxLB.innerHTML = '&nbsp;';
    var roundBoxRB = document.createElement('div');
    roundBoxRB.setAttribute('class', 'roundbox-rb');
    roundBoxRB.innerHTML = '&nbsp;';
    roundBox.appendChild(roundBoxLT);
    roundBox.appendChild(roundBoxRT);
    // roundBox.appendChild(roundBoxLB);
    // roundBox.appendChild(roundBoxRB);
    return roundBox;
}

function createCodeforcesLikeDeleteButton (problemTitle) {
    var deleteBtn = document.createElement('a');
    deleteBtn.setAttribute('class', 'delete-virtual-contest');
    deleteBtn.setAttribute('title', 'delete [' + problemTitle + ']');
    deleteBtn.setAttribute('href', '#');
    var img = document.createElement('img');
    img.setAttribute('width', '12px;');
    img.setAttribute('src', '//sta.codeforces.com/s/!/images/delete.png');
    deleteBtn.appendChild(img);
    return deleteBtn;
}

function setProblemList () {
    var userPage = document.getElementsByClassName('avatar')[0].querySelectorAll('a')[1];
    if(userPage == null || (userPage != location.href && userPage + "#" != location.href)) return;

    var roundBox = createCodeforcesLikeRoundBox();

    var title = document.createElement('div');
    title.setAttribute('class', 'caption titled');
    title.innerHTML = '→ Problem queue';
    roundBox.appendChild(title);

    var table = document.createElement('table');
    table.setAttribute('class', 'rtable ');
    table.setAttribute('id', 'problemQueue');
    roundBox.appendChild(table);
    var tbody = document.createElement('tbody');
    table.appendChild(tbody);

    var header = document.createElement('tr');
    var thIdx = document.createElement('th');
    thIdx.textContent = '#';
    var thPblm = document.createElement('th');
    thPblm.textContent = 'Problem';
    header.appendChild(thIdx);
    header.appendChild(thPblm);
    header.appendChild(document.createElement('th'));
    tbody.appendChild(header);

    var num = 1;
    var problemQueue = getProblemQueue();
    for (let key in problemQueue) {
        var tr = document.createElement('tr');
        // add index
        var tdIdx = document.createElement('td');
        tdIdx.innerText = num;
        if(num%2) tdIdx.setAttribute('class', 'dark');
        // add problem link
        var tdLink = document.createElement('td');
        if(num%2) tdLink.setAttribute('class', 'dark');
        tdLink.innerHTML = '<a href="' + problemQueue[key].problemLink + '" title="' + problemQueue[key].contestName + '" target="_blank" rel="noopener noreferrer">' + key + '</a>';
        // add delete button
        var tdBtn = document.createElement('td');
        if(num%2) tdBtn.setAttribute('class', 'dark');
        tdBtn.appendChild(createCodeforcesLikeDeleteButton(key));
        tr.appendChild(tdIdx);
        tr.appendChild(tdLink);
        tr.appendChild(tdBtn);
        tbody.appendChild(tr);
        num++;
    }
    document.getElementById('pageContent').appendChild(roundBox);

    document.querySelectorAll('.delete-virtual-contest').forEach ( (btn) => btn.addEventListener (
        'click', {obj: btn, handleEvent: deleteAction}, false
    ));
}

function deleteAction (event) {
    var tr = this.obj.parentNode.parentNode;
    var problemTitle = tr.querySelectorAll('a')[0].text;
    deleteProblem(problemTitle);
    tr.parentNode.deleteRow(tr.sectionRowIndex);
}

(function() {
    var url = window.location.href;

    if( url.match(new RegExp('/codeforces.com\/contest\/(.*)\/problem\/(.*)')) != null ) {
        setAddProblemButton();
    } else if ( url.match(new RegExp('/codeforces.com\/profile\/(.*)')) != null) {
        setProblemList();
    }
})();