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