您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
洛谷超级任务计划(第三方),不限题目数量
当前为
// ==UserScript== // @name 洛谷超级任务计划(第三方) // @namespace http://tampermonkey.net/ // @version 1.2 // @description 洛谷超级任务计划(第三方),不限题目数量 // @author Anguei, Legendword // @match https://www.luogu.org/problemnew/show/* // @match https://www.luogu.org/ // @grant GM_setValue // @grant GM_getValue // ==/UserScript== // 可能将要实现的功能: // 1. 添加首页的编辑题目按钮 // 2. 当 todolist 的 size 小于 30 时,新加入 superTodolist 的题目同步加入洛谷官方 todolist // 3. 从 superTodolist 删除题目时,若题目也在洛谷官方 todolist 当中,同步删除 // 4. superTodolist 的导入与导出(以便于与 memset0 的项目配合,以及换电脑之后 superTodolist 的同步) // 感谢 @memset0 提供创意 // 感谢 @Legendword 协助完成 jQuery 相关代码 // 感谢 @memset0, @Legendword 帮助找 bug var version = '1.2' var nowUrl = window.location.href; var LuoguSuperTodolist = { settings: { keepOriginalList: false } }; var myUid = document.cookie.match(/[0-9]+/)[0]; console.log(myUid) console.log('如果上面获取到的 uid 不正确,请反馈作者,谢谢') function syncList() { console.log('syncing'); var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://www.luogu.org/', false); xhr.send(null); if (xhr.status == 200) { console.log('get original todo list: 200'); var problems = extractData(xhr.responseText); LuoguSuperTodolist.problems = problems; initList(); // 把洛谷原计划保存到脚本 } else { return {}; } function extractData(content) { var psid = content.split('" target="_blank"><b>'); var problems = clearData(psid); // console.log(problems); return problems; function clearData(psid) { // psid: problems' id var res = {} for (var i = 1; i < psid.length; i++) { // 从 1 开始循环,因为 split 导致 psid[0] 是垃圾文本串 var pId = '', pName = '', j = 0; for (; j < psid[i].length; j++) { // 获取题号 if (psid[i][j] != '<') { pId = pId.concat(psid[i][j]); } else break; } for (j += 5; j < psid[i].length; j++) { // 获取题目名称 if (psid[i][j] != '<') { pName = pName.concat(psid[i][j]); } else break; } res[pId] = pName; if (psid[i].match(/智能推荐/) != null) break; } return res; } } function initList() { var old = GM_getValue('problems'); if (old != undefined || old != 'undefined') { for (var i in old) { LuoguSuperTodolist.problems[i] = old[i] } } GM_setValue('problems', LuoguSuperTodolist.problems); } } function getAc(uid) { // 从原来代码复制过来的 // 向指定的个人空间发送 get 请求,获取 AC 列表 var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://' + window.location.host + '/space/show?uid=' + uid, false); xhr.send(null); console.log('got ' + uid + "'s AC list: " + xhr.status); if (xhr.status == 200) { return extractData(xhr.responseText); // 返回 AC 列表 } else { return []; // 空列表 } function extractData(content) { // 如果你有一个问题打算用正则表达式来解决,那么就是两个问题了。 // 所以窝还是用 split() 解决这一个问题吧! var acs = content.replace(/<span style=\"display:none\">\n.*?\n<\/span>/g, ''); // 把随机的干扰题号去除 acs = acs.split('[<a data-pjax href="/problem/show?pid='); // 使用 split() 方法把通过的题目分割出来 acs = clearData(acs); // 把分割好的数据清洁一下 return acs; function clearData(acs) { var res = new Array(); res.push(new Array()); res.push(new Array()); var g = 0; for (var i = 1; i < acs.length; i++) { // 把每一行非题号字符删掉(从 1 开始循环为了避开 split 之后产生的垃圾) var tmpStr = ""; for (var j = 0; j < acs[i].length; j++) { if (acs[i][j] != '"') { // 引号后面的不是题号部分字符 tmpStr = tmpStr.concat(acs[i][j]); // 拼接字符串 } else break; } res[g].push(tmpStr); if (acs[i].length > 50) { // 这是最后一个题目 / 下一个是「尝试过的题目」 g++; } } return res; } } } function updateMainPageList() { var tmp = getAc(myUid); var myAc = tmp[0], myAttempt = tmp[1]; myAc.sort(); myAttempt.sort(); // 清除官方的任务计划 if (!LuoguSuperTodolist.settings.keepOriginalList) { $("h2:contains('智能推荐')").prevAll().remove(); } // 在 Luogu 官方任务计划后面添加第三方计划 var problems = GM_getValue('problems') $("h2:contains('智能推荐')").before('<h2>任务计划</h2>'); for (var i in problems) { var state = getState(i); var color = { 'Y': 'green', 'N': 'black', '?': 'orange' }; var content = { 'Y': '<i class="am-icon-check"></i>', 'N': '<i class="am-icon-minus"></i>', '?': '?' }; $("h2:contains('智能推荐')").before( '<div class="tasklist-item" data-pid="' + i + '"><div><a href="/recordnew/lists?uid=' + myUid + '&pid=' + i + '" target="_blank"><strong class="lg-fg-' + color[state] + '">' + content[state] + '</strong></a>' + '<a class="colored" style="padding-left: 3px" href="/problemnew/show/' + i + '" target="_blank"><b>' + i + '</b> ' + problems[i] + '</a></div></div>' ); } function getState(pid) { if (binarySearch(pid, myAc)) return 'Y'; else if (binarySearch(pid, myAttempt)) return '?'; else return 'N'; } function binarySearch(target, array) { // 使用二分查找算法进行比较 var l = 0, r = array.length; while (l < r) { var mid = parseInt((l + r) / 2); // JavaScript 除法默认不是整数。。 if (target == array[mid]) return true; else if (target > array[mid]) l = mid + 1; else r = mid; } return false; } } function addButton() { $('#remove-tasklist').remove(); $('#add-tasklist').remove(); // 移除旧的按钮 var problemId = nowUrl.match(/[A-Z]+[0-9]+/)[0]; var problemTitle = getTitle(); if (!isInList()) { $(".lg-summary-content") .append('<p>' + '<a href="javascript: ;" ' + 'id="update-todolist" ' + 'class="am-btn am-btn-sm am-btn-primary">' + '添加至超级任务计划' + '</a>' + '</p>'); $("#update-todolist").click(swapState); } else { $(".lg-summary-content") .append('<p>' + '<a href="javascript: ;" ' + 'id="update-todolist" ' + 'class="am-btn am-btn-sm am-btn-danger">' + '从任务计划移除' + '</a>' + '</p>'); $("#update-todolist").click(swapState); } function getTitle() { return document.title.substr((problemId.length + 1), document.title.length - (problemId.length + 1) - 5) } function isInList() { var nowList = GM_getValue('problems'); if (nowList == undefined) return false; return nowList[problemId] != undefined; } function swapState(ev) { // 是不是应该改成检测现在的属性,然后交换属性 if (isInList()) { // 已经在任务计划列表,删掉它。变成蓝色按钮 removeFromList(problemId, problemTitle); $("#update-todolist").attr("class", "am-btn am-btn-sm am-btn-primary"); $("#update-todolist").html("添加至超级任务计划"); } else { // 不在任务计划当中,加进去,变成红色按钮 addToList(problemId, problemTitle) $("#update-todolist").attr("class", "am-btn am-btn-sm am-btn-danger"); $("#update-todolist").html("从任务计划移除"); } function addToList(id, title) { var nowList = GM_getValue('problems'); nowList[id] = title; GM_setValue('problems', nowList); } function removeFromList(id, title) { var nowList = GM_getValue('problems'); delete nowList[id]; GM_setValue('problems', nowList) } } } function start() { var lastVersion = GM_getValue('version'); if (lastVersion != version) { // 首次运行脚本,将原任务计划保存 console.log('更新后首次运行脚本,请耐心等待初始化'); syncList(); } if (nowUrl == 'https://www.luogu.org/') { updateMainPageList(); // 更新主页的 todolist } else if (nowUrl.match(/problem/) != null) { // 题目页面运行脚本,添加按钮 addButton(); } GM_setValue('version', version); } start();