leetcode-cn辅助

leetcode-cn刷题辅助脚本

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==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);
    }
}