Greasy Fork 支持简体中文。

leetcode-cn辅助

leetcode-cn刷题辅助脚本

// ==UserScript==
// @name         leetcode-cn辅助
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  leetcode-cn刷题辅助脚本
// @author       You
// @match        https://leetcode-cn.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

let featured = new Set([838,1469,1469,1681,1681,1538,1538,1906,1906,1669,1669,1582,1582,1581,1581,1448,1448,1542,1542,1638,1638,1590,1590,1679,1679,1484,1484,1651,1651,1630,1630,1592,1592,1384,1384,1485,1485,1682,1682,1533,1533,1676,1676,999,999,1540,1540,1628,1628,1571,1571,1579,1579,1536,1536,821,821,485,485,1541,1541,1444,1444,1586,1586,1665,1665,1645,1645,1606,1606,1519,1519,1620,1620,1653,1653,1591,1591,1622,1622,1531,1531,1636,1636,1602,1602,1650,1650,111,111,1222,1222,1555,1555,730,730,1362,1362,1522,1522,1505,1505,1641,1641,1908,1908,1625,1625,1660,1660,1196,1196,1662,1662,1011,1011,1475,1475,1907,1907,1903,1903,1300,1300,1486,1486,1539,1539,1546,1546,1356,1356,1178,1178,1044,1044,1290,1290,1457,1457,1495,1495,1605,1605,1397,1397,1454,1454,1904,1904,978,978,1673,1673,1532,1532,1610,1610,1142,1142,1593,1593,1570,1570,1634,1634,1623,1623,1248,1248,1916,1916,1911,1911,1637,1637,1471,1471,1463,1463,93,93,1144,1144,1240,1240,1247,1247,1199,1199,1621,1621,1477,1477,1644,1644,1564,1564,1476,1476,84,84,1598,1598,1629,1629,1924,1924,1910,1910,1609,1609,1172,1172,1036,1036,1668,1668,1014,1014,1578,1578,1550,1550,1337,1337,1282,1282,102,102,1028,1028,91,91,1378,1378,933,933,1909,1909,1545,1545,1667,1667,1152,1152,1666,1666,1180,1180,1678,1678,1923,1923,1268,1268,101,101,1613,1613,812,812,108,108,1446,1446,1253,1253,1234,1234,1298,1298,1420,1420,1511,1511,1604,1604,1547,1547,1424,1424,1534,1534,1159,1159,1474,1474,701,701,1245,1245,1462,1462,1135,1135,1368,1368,313,313,1518,1518,916,916,133,133,1306,1306,1639,1639,1567,1567,1059,1059,1350,1350,182,182,1588,1588,1921,1921,776,776,395,395,1174,1174,781,781,1648,1648,1284,1284,831,831,1611,1611,799,799,1595,1595,1914,1914,1315,1315,1575,1575,1635,1635,885,885,1191,1191,1241,1241,949,949,1557,1557,846,846,326,326,1913,1913,953,953,96,96,95,95,864,864,1607,1607,1308,1308,473,473,693,693,1912,1912,1263,1263,110,110,713,713,892,892,1120,1120,1322,1322,79,79,1464,1464,341,341,1252,1252,1537,1537,995,995,1012,1012,132,132,1347,1347,849,849,617,617,637,637,1286,1286,1019,1019,1554,1554,939,939,475,475,137,137,439,439,1672,1672,1824,1824,757,757,1603,1603,721,721,121,121,959,959,452,452,441,441,425,425,359,359,697,697,1915,1915,573,573,809,809,166,166,1353,1353,99,99,472,472,311,311,72,72,1790,1790,1568,1568,1766,1766,1052,1052,1093,1093,1287,1287,528,528,187,187,1183,1183,162,162,902,902,1323,1323,1319,1319,481,481,1239,1239,1553,1553,1150,1150,245,245,1655,1655,1920,1920,1095,1095,1373,1373,1405,1405,642,642,1740,1740,1302,1302,331,331,815,815,1365,1365,1377,1377,1004,1004,703,703,1880,1880,493,493,144,144,1425,1425,769,769,1888,1888,1366,1366,1922,1922,1359,1359,1341,1341,413,413,1255,1255,737,737,828,828,496,496,1260,1260,1018,1018,1033,1033,773,773,135,135,1407,1407,1429,1429,555,555,1140,1140,1048,1048,105,105,852,852,1181,1181,1069,1069,71,71,714,714,129,129,1431,1431,300,300]);
let too_easy = new Set();

(function() {
    'use strict';

    read_config();

    // 注册监听
    when(detectTable, () => {
        let tableObserver = new MutationObserver(process_problem_list);
        let options = {childList: true};
        let table = get_problem_list_dom();
        let tbody = table.getElementsByTagName('tbody')[0];
        tableObserver.observe(tbody, options);
    });
    when(detectTable, process_problem_list);
})();

function save_config() {
    GM_setValue('easy_list', too_easy);
}

function read_config() {
    too_easy = GM_getValue('easy_list');
    too_easy = new Set(too_easy);
    if (too_easy === undefined) {
        too_easy = new Set();
    }
}

// 用于判断表格是否被加载
function detectTable() {
    let table = get_problem_list_dom();
    if (table === undefined) {
        return false;
    }
    let tr = table.getElementsByTagName('tr')[0];
    if (tr === undefined) {
        return false;
    }
    return true;
}

function get_problem_list_dom() {
    return document.getElementsByClassName('table-striped')[0];
}

// 处理问题列表
function process_problem_list() {
    console.log('called');
    let table = get_problem_list_dom();
    let trs = table.getElementsByTagName('tr');

    for (let i = 1 ; i < trs.length-1 ; i++) {
        let row = get_row_data(trs[i]);
        console.log(row);
        // 删除操作
        if (should_delete_problem(row)) {
            delete_row(trs[i]);
            continue;
        }

        // 修改操作
        modify_row(trs[i], row);

    }
}

function should_delete_problem(row) {
    if (row.difficulty == '简单') return true;
    if (row.status == 'locked') return true;
    return false;
}

function get_row_data(tr) {
    let tds = tr.getElementsByTagName('td');
    let row = {};

    /*
    第一个字段,题目状态
    locked: 锁定题目
    solved: 已完成
    failed: 已尝试,未通过
    empty: 未尝试
    */
    let div = tds[0].firstElementChild;
    if (div.firstElementChild == null) {
        row.status = 'empty';
    } else {
        let span = div.firstElementChild;
        if (span.classList.contains('lock__13du')) {
            row.status = 'locked';
        } else if (span.classList.contains('text-success')) {
            row.status = 'solved';
        } else if (span.classList.contains('text-info')) {
            row.status = 'failed';
        } else {
            row.status = 'empty';
        }
    }

    /*
    第二个字段,id
    */
    let problem_id = Number(tds[1].innerText);
    row.problem_id = problem_id;

    /*
    第三个字段,题目名
    */
    let title = tds[2].getElementsByTagName('a')[0].innerText;
    row.title = title;

    /*
    第四个字段,题解数量
    */
    let num_of_solution = Number(tds[3].firstElementChild.innerText);
    row.solution_num = num_of_solution;

    /*
    第五个字段,通过率
    */
    let pass_rate = tds[4].innerText;
    row.pass_rate = pass_rate;

    /*
    第六个字段,难度
    */
    let difficulty = tds[5].firstElementChild.innerText;
    row.difficulty = difficulty;

    return row;
}

function modify_row(tr, row) {
    // 修改一行的显示
    // 1. 标记常考的题
    if (featured.has(row.problem_id)) {
        tr.style.backgroundColor = '#5ABE6F';
    }

    // 2. 修改链接,能够在新窗口打开
    let link_td = tr.children[2];
    // 移除原来的链接,添加新的链接
    let href = link_td.firstChild.firstChild.firstChild.href;
    let a = document.createElement('a');
    a.innerText = link_td.innerText;
    a.href = href;
    link_td.removeChild(link_td.firstChild);
    link_td.appendChild(a);

    // 3. 添加本地标记功能 TODO
    console.log(too_easy);
    if (too_easy.has(row.problem_id)) {
        add_easy_mark(tr.children[0]);
    }
    tr.children[0].addEventListener('click', () => {
        if (too_easy.has(row.problem_id)) {
            too_easy.delete(row.problem_id);
            remove_easy_mark(tr.children[0]);
        } else {
            too_easy.add(row.problem_id);
            add_easy_mark(tr.children[0]);
        }
        save_config();
        //add_easy_mark(tr.children[0]);
    });
}

function contains_easy_mark(td) {
    let div = td.firstElementChild;
    let spans = div.getElementsByClassName('fa-check-circle-o');
    return spans.length != 0;
}
function add_easy_mark(td) {
    let div = td.firstElementChild;
    let spans = div.getElementsByClassName('fa-check-circle-o');
    if (spans.length == 0) {
        let span = document.createElement('span');
        span.classList.add('fa');
        span.classList.add('fa-check-circle-o');
        div.appendChild(span);
    }
}

function remove_easy_mark(td) {
    let div = td.firstElementChild;
    let spans = div.getElementsByClassName('fa-check-circle-o');
    for (let i = 0 ; i < spans.length ; i++) {
        spans[i].remove();
    }
}

function delete_row(tr) {
    //tr.remove();
    tr.setAttribute('hidden', true);
}

function when(condition,func) {
    if (condition()) {
        func();
    } else {
        window.setTimeout(() => {when(condition, func)},1000);
    }
}