BZOJ Helper

BZOJ助手

  1. // ==UserScript==
  2. // @name BZOJ Helper
  3. // @namespace bzoj
  4. // @version 1.5.4
  5. // @description BZOJ助手
  6. // @author ranwen
  7. // @match https://lydsy.com/*
  8. // @match https://www.lydsy.com/*
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. String.prototype.trim = function () {
  14. return this.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
  15. }
  16. function savedata(name, val) {
  17. localStorage.setItem(name, JSON.stringify(val));
  18. }
  19. function readdata(name) {
  20. return JSON.parse(localStorage.getItem(name))
  21. }
  22. function getradioval(name) {
  23. for (i of document.getElementsByName(name)) {
  24. if (i.checked) {
  25. return i.value;
  26. }
  27. }
  28. }
  29. Date.prototype.Format = function (fmt) { //author: meizz
  30. var o = {
  31. "M+": this.getMonth() + 1, //月份
  32. "d+": this.getDate(), //日
  33. "h+": this.getHours(), //小时
  34. "m+": this.getMinutes(), //分
  35. "s+": this.getSeconds(), //秒
  36. "q+": Math.floor((this.getMonth() + 3) / 3), //季度
  37. "S": this.getMilliseconds() //毫秒
  38. };
  39. if (/(y+)/.test(fmt))
  40. fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
  41. for (var k in o)
  42. if (new RegExp("(" + k + ")").test(fmt))
  43. fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
  44. return fmt;
  45. }
  46. function HaveMatch(txt, arr) {
  47. for (let i of arr) {
  48. if (txt.indexOf(i) != -1) return 1;
  49. }
  50. return 0;
  51. }
  52. var poly_star = "<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" style=\"width: 20px;height: 20px;\">\
  53. <polygon points=\"19.510565162951536,6.9098300562505255 12.351141009169893,6.76393202250021 10,0 7.648858990830108,6.76393202250021 0.48943483704846535,6.9098300562505255 6.195773934819385,11.236067977499792 4.122147477075267,18.090169943749473 10,14 15.87785252292473,18.090169943749476 13.804226065180615,11.23606797749979\" style=\"fill:#FFFF00;\"></polygon>\
  54. </svg>";
  55. var logined = 0
  56. var username = "";
  57. var mydb = Array();
  58. var markedp = Array();
  59. var fixurl = location.href;
  60. var havenotice = 0;
  61. if (document.getElementsByTagName("center")[1].innerText.indexOf("Notice") != -1) havenotice = 1;
  62. if (fixurl.indexOf("www.lydsy.com") != -1) {
  63. fixurl = fixurl.replace("www.lydsy.com", "lydsy.com");
  64. location.href = fixurl;
  65. }
  66. function getmyusername() {
  67. for (i of document.getElementsByTagName("table")[0].childNodes[1].childNodes[0].childNodes)
  68. if (typeof (i.innerText) != "undefined" && i.innerText.indexOf("ModifyUser") != -1) {
  69. username = i.innerText.substr(12);
  70. username = username.trim();
  71. return;
  72. }
  73. logined = -1;
  74. }
  75. //页面判断
  76. function isprob() {
  77. if (fixurl.indexOf("https://lydsy.com/JudgeOnline/problem.php?id=") == -1) {
  78. return -1;
  79. }
  80. return fixurl.substr(45);
  81. }
  82. function isstatus() {
  83. if (fixurl.indexOf("https://lydsy.com/JudgeOnline/status.php") == -1) {
  84. return -1;
  85. }
  86. return 0;
  87. }
  88. function islist() {
  89. if (fixurl.indexOf("https://lydsy.com/JudgeOnline/problemset.php") == -1) {
  90. return -1;
  91. }
  92. return 0;
  93. }
  94. function isconfig() {
  95. if (fixurl.indexOf("https://lydsy.com/JudgeOnline/modifypage.php") == -1) {
  96. return -1;
  97. }
  98. return 0;
  99. }
  100. function isdiscusspage() {
  101. if (fixurl.indexOf("https://lydsy.com/JudgeOnline/wttl/thread.php") == -1) {
  102. return -1;
  103. }
  104. return 0;
  105. }
  106. function isdiscusslist() {
  107. if (fixurl.indexOf("https://lydsy.com/JudgeOnline/wttl/wttl.php") == -1) {
  108. return -1;
  109. }
  110. return 0;
  111. }
  112. function isuserinfo() {
  113. if (fixurl.indexOf("https://lydsy.com/JudgeOnline/userinfo.php?user=") == -1) {
  114. return -1;
  115. }
  116. return 0;
  117.  
  118. }
  119. //更新db
  120. function updateprobinfobypage(pid) {
  121. sb = {};
  122. for (i of document.getElementsByTagName("h2")[0].childNodes)
  123. if (i.nodeName == "#text") {
  124. sb["title"] = i.data.substr(6)
  125. break
  126. }
  127. sb["submit"] = document.getElementsByTagName("center")[1 + havenotice].getElementsByClassName("green")[2].nextSibling.data;
  128. sb["submit"] = sb["submit"].slice(0, -2);
  129. sb["solved"] = document.getElementsByTagName("center")[1 + havenotice].getElementsByClassName("green")[3].nextSibling.data;
  130. sb["source"] = document.getElementsByTagName("h2")[7].nextElementSibling.childNodes[0].innerText;
  131. savedata("problem_" + pid, sb)
  132. }
  133. function updateprobinfobylist() {
  134. for (i of document.getElementById("problemset").getElementsByTagName("tbody")[0].childNodes) {
  135. sb = {}
  136. prob = i.childNodes[1].innerText.trim();
  137. sb["title"] = i.childNodes[2].innerText.trim();
  138. sb["source"] = i.childNodes[3].innerText.trim();
  139. sb["solved"] = i.childNodes[4].innerText.trim();
  140. sb["submit"] = i.childNodes[5].innerText.trim();
  141. if (i.childNodes[0].innerText.trim() == "Y") {
  142. if (mydb.indexOf(prob) == -1)
  143. mydb.push(prob)
  144. }
  145. savedata("problem_" + prob, sb)
  146. }
  147. savedata("userlist_" + username, mydb)
  148. }
  149. function updateuserdb(def = document, nm = fixurl.substr(48)) {
  150. var list = def.getElementsByTagName("script")[2].innerHTML.match(/p\([1-9][0-9]{3}\)/g);
  151. var rl = Array();
  152. for (var i of list) {
  153. rl.push(i.substr(2, 4))
  154. }
  155. savedata("userlist_" + nm, rl)
  156. }
  157. function getmydb() {
  158. ret = readdata("userlist_" + username);
  159. if (ret == null) {
  160. xhr = new XMLHttpRequest();
  161. xhr.open('GET', 'https://lydsy.com/JudgeOnline/userinfo.php?user=' + username, false);
  162. xhr.send(null);
  163. parser = new DOMParser();
  164. gg = parser.parseFromString(xhr.responseText, "text/html")
  165. updateuserdb(gg, username)
  166. ret = readdata("userlist_" + username)
  167. }
  168. return ret
  169. }
  170. function UpdateBlacklist(callb = 0) {
  171. URL = "https://raw.githubusercontent.com/ranwen/BZOJHelper/master/blacklist.json";
  172. xhr = new XMLHttpRequest();
  173. xhr.open('GET', URL, false);
  174. xhr.send(null);
  175. obj = JSON.parse(xhr.responseText)
  176. res = { "updatetime": ((new Date()) / 1000), "user": obj.user, "title": obj.title }
  177. Blacklist = res
  178. savedata("blacklist", res)
  179. if (callb == 1)
  180. alert("更新成功 请刷新");
  181. }
  182. function UpdateBlacklistAsync(callb = 0) {
  183. setTimeout(UpdateBlacklist(callb), 1)
  184. }
  185. function CheckUpdateBlacklist() {
  186. nowt = (new Date()) / 1000
  187. if (nowt - Blacklist["updatetime"] < 7 * 24 * 3600) return;
  188. UpdateBlacklistAsync();
  189. }
  190. function setdefaultconfig() {
  191. def = { "unmarkalert": "0", "autoext": "1", "statusny": "1", "AutoUpdateBlacklist": "1", "Blacklist": "1" };
  192. for (i in def) {
  193. if (typeof (config[i]) == "undefined")
  194. config[i] = def[i];
  195. }
  196. savedata("config", config);
  197. }
  198. getmyusername()
  199. if (logined == -1) {
  200. return;
  201. }
  202. markedp = readdata("marked");
  203. if (markedp == null) {
  204. savedata("marked", Array());
  205. markedp = Array();
  206. }
  207. config = readdata("config");
  208. if (config == null) {
  209. savedata("config", {});
  210. config = {};
  211. }
  212. setdefaultconfig();
  213. Blacklist = readdata("blacklist");
  214. if (Blacklist == null) {
  215. savedata("blacklist", { "updatetime": 0, "user": [], "title": [] });
  216. Blacklist = { "updatetime": 0, "user": [], "title": [] };
  217. }
  218. if (config["AutoUpdateBlacklist"] == "1")
  219. CheckUpdateBlacklist();
  220. //page
  221. if (isuserinfo() != -1) {
  222. updateuserdb();
  223. document.getElementsByTagName("table")[1].getElementsByTagName("tr")[0].getElementsByTagName("td")[2].innerHTML += " <a href=\"javascript:;\" id=\"diffme\">Diff with me</a>"
  224. document.getElementById("diffme").onclick = function () {
  225. nm = fixurl.substr(48)
  226. txt = ""
  227. usdb = readdata("userlist_" + nm)
  228. for (i = 1000; i <= 9999; i++) {
  229. hs1 = (mydb.indexOf("" + i) != -1)
  230. hs2 = (usdb.indexOf("" + i) != -1)
  231. if (hs1 && hs2)
  232. txt += "<a href=\"problem.php?id=" + i + "\">" + i + "</a>\n"
  233. if (hs1 && (!hs2))
  234. txt += "<a href=\"problem.php?id=" + i + "\" style=\"color:#00FF00\">" + i + "</a>\n"
  235. if ((!hs1) && hs2)
  236. txt += "<a href=\"problem.php?id=" + i + "\" style=\"color:#FF0000\">" + i + "</a>\n"
  237. }
  238. document.getElementsByTagName("table")[1].getElementsByTagName("tr")[1].getElementsByTagName("td")[2].innerHTML = txt
  239. }
  240. }
  241.  
  242. mydb = getmydb();
  243. if (islist() != -1) {
  244. updateprobinfobylist();
  245. for (i of document.getElementById("problemset").getElementsByTagName("tbody")[0].childNodes) {
  246. prob = i.childNodes[1].innerText.trim();
  247. if (markedp.indexOf(prob) != -1) i.childNodes[2].innerHTML = i.childNodes[2].innerHTML + poly_star;
  248. }
  249. document.getElementById("problemset").getElementsByTagName("thead")[0].childNodes[1].childNodes[0].childNodes[0].innerHTML = document.getElementById("problemset").getElementsByTagName("thead")[0].childNodes[1].childNodes[0].childNodes[0].innerHTML +
  250. " <a href=\"javascript:;\" id=\"showmarkedlist\">Marked Problem(" + markedp.length + ")</a>";
  251. document.getElementById("showmarkedlist").onclick = function () {
  252. document.getElementById("problemset").getElementsByTagName("thead")[0].childNodes[1].childNodes[0].childNodes[0].innerHTML += " <a href=\"javascript:;\" id=\"unmarkac\">Unmark AC Problem</a>";
  253. txt = ""
  254. for (i = 0; i < markedp.length; i++) {
  255. o = markedp[i]
  256. info = readdata("problem_" + o);
  257. nr = ""
  258. nr += "<tr class=\"" + ((i & 1) == 0 ? "evenrow" : "oddrow") + "\">";
  259. nr += "<td>";
  260. if (mydb.indexOf(o) != -1) nr += "<span class=\"yes\">Y</span>";
  261. nr += "</td>";
  262. nr += "<td align=\"center\">";
  263. nr += o;
  264. nr += "</td>";
  265. nr += "<td align=\"left\">";
  266. nr += "<a href=\"problem.php?id=" + o + "\">" + info['title'] + "</a>" + poly_star;
  267. nr += "</td>"
  268. nr += "<td align=\"center\">";
  269. nr += info['source']
  270. nr += "</td>";
  271. nr += "<td align=\"center\">";
  272. nr += "<a href=\"status.php?problem_id=" + o + "&amp;jresult=4\">" + info['solved'] + "</a>";
  273. nr += "</td>";
  274. nr += "<td align=\"center\">";
  275. nr += "<a href=\"status.php?problem_id=" + o + "\">" + info['submit'] + "</a>";
  276. nr += "</td>";
  277. nr += "</tr>";
  278. txt += nr;
  279. }
  280. document.getElementById("problemset").getElementsByTagName("tbody")[0].innerHTML = txt;
  281.  
  282. //show unmarkac
  283. document.getElementById("unmarkac").onclick = function () {
  284. if (!window.confirm("确定取消标记所有AC题目?")) return
  285. markedp = readdata("marked")
  286. for (i = 0; i < markedp.length; i++) {
  287. o = markedp[i]
  288. if (mydb.indexOf(o) != -1) {
  289. markedp.splice(markedp.indexOf(o), 1)
  290. i--
  291. }
  292. }
  293. savedata("marked", markedp)
  294. //rerender
  295. txt = ""
  296. for (i = 0; i < markedp.length; i++) {
  297. o = markedp[i]
  298. info = readdata("problem_" + o);
  299. nr = ""
  300. nr += "<tr class=\"" + ((i & 1) == 0 ? "evenrow" : "oddrow") + "\">";
  301. nr += "<td>";
  302. if (mydb.indexOf(o) != -1) nr += "<span class=\"yes\">Y</span>";
  303. nr += "</td>";
  304. nr += "<td align=\"center\">";
  305. nr += o;
  306. nr += "</td>";
  307. nr += "<td align=\"left\">";
  308. nr += "<a href=\"problem.php?id=" + o + "\">" + info['title'] + "</a>" + poly_star;
  309. nr += "</td>"
  310. nr += "<td align=\"center\">";
  311. nr += info['source']
  312. nr += "</td>";
  313. nr += "<td align=\"center\">";
  314. nr += "<a href=\"status.php?problem_id=" + o + "&amp;jresult=4\">" + info['solved'] + "</a>";
  315. nr += "</td>";
  316. nr += "<td align=\"center\">";
  317. nr += "<a href=\"status.php?problem_id=" + o + "\">" + info['submit'] + "</a>";
  318. nr += "</td>";
  319. nr += "</tr>";
  320. txt += nr;
  321. }
  322. document.getElementById("problemset").getElementsByTagName("tbody")[0].innerHTML = txt;
  323. document.getElementById("showmarkedlist").innerText = "Marked Problem(" + markedp.length + ")";
  324. }
  325. }
  326. }
  327.  
  328. var prob = isprob();
  329. if (prob != -1) {
  330. updateprobinfobypage(prob)
  331. if (mydb.indexOf(prob) != -1) {
  332. var rdt = document.getElementsByTagName("center")[1 + havenotice].getElementsByTagName("h2")[0].innerHTML;
  333. var tdb = "<span style=\"color:#00FF00\">Y</span>" + rdt;
  334. document.getElementsByTagName("center")[1 + havenotice].getElementsByTagName("h2")[0].innerHTML = tdb;
  335. }
  336. var ttt = document.getElementsByTagName("center")[1 + havenotice].innerHTML;
  337. var fff = ttt + "[<a href=\"https://lydsy.com/JudgeOnline/status.php?problem_id=" + prob + "&user_id=" + username + "\">My Status</a>]";
  338. document.getElementsByTagName("center")[1 + havenotice].innerHTML = fff;
  339. var rdt = document.getElementsByTagName("center")[1 + havenotice].getElementsByTagName("h2")[0].innerHTML;
  340. col = "#cccccc"
  341. if (markedp.indexOf(prob) != -1) col = "#FFFF00";
  342. var tdb = rdt +
  343. "<a href=\"javascript:;\" id=\"chmr\"><svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" style=\"width: 20px;height: 20px;\">\
  344. <polygon points=\"19.510565162951536,6.9098300562505255 12.351141009169893,6.76393202250021 10,0 7.648858990830108,6.76393202250021 0.48943483704846535,6.9098300562505255 6.195773934819385,11.236067977499792 4.122147477075267,18.090169943749473 10,14 15.87785252292473,18.090169943749476 13.804226065180615,11.23606797749979\" style=\"fill:"+ col + ";\"></polygon>\
  345. </svg></a>";
  346. document.getElementsByTagName("center")[1 + havenotice].getElementsByTagName("h2")[0].innerHTML = tdb;
  347.  
  348. document.getElementById("chmr").onclick = function () {
  349. markedp = readdata("marked");
  350. if (markedp.indexOf(prob) != -1) {
  351. if (config["unmarkalert"] == "1" && !window.confirm("确定鸽掉它?")) return; //取消标记提示
  352. markedp.splice(markedp.indexOf(prob), 1)
  353. document.getElementsByTagName("center")[1 + havenotice].getElementsByTagName("h2")[0].getElementsByTagName("a")[0].childNodes[0].childNodes[1].style.fill = "#cccccc"
  354. }
  355. else {
  356. markedp.push(prob)
  357. document.getElementsByTagName("center")[1 + havenotice].getElementsByTagName("h2")[0].getElementsByTagName("a")[0].childNodes[0].childNodes[1].style.fill = "#FFFF00"
  358. }
  359. markedp.sort()
  360. savedata("marked", markedp)
  361. }
  362. }
  363.  
  364. if (isstatus() != -1) {
  365. for (var i of document.getElementsByTagName("center")[0].getElementsByTagName("table")[2].getElementsByTagName("tbody")[0].childNodes) {
  366. if (i.className != "evenrow" && i.className != "oddrow") continue;
  367. prob = i.childNodes[2].childNodes[0].innerText.trim();
  368. user = i.childNodes[1].childNodes[0].innerText.trim();
  369. stat = i.childNodes[3].childNodes[0].innerText.trim();
  370. if (stat == "Accepted" && readdata("userlist_" + user) != null) {
  371. udb = readdata("userlist_" + user)
  372. if (udb.indexOf(prob) == -1)
  373. udb.push(prob)
  374. savedata("userlist_" + user, udb)
  375. if (user == username)
  376. mydb.push(prob)
  377. }
  378. mkd = ""
  379. if (markedp.indexOf(prob) != -1)
  380. mkd = poly_star;
  381. if (mydb.indexOf(prob) != -1) {
  382. fky = "<span style=\"color:#00FF00\">Y</span>";
  383. }
  384. else {
  385. fky = "<span style=\"color:#FF0000\">N</span>";
  386. }
  387.  
  388. if (config['statusny'] == "0") fky = ""
  389. i.childNodes[2].childNodes[0].innerHTML = fky + i.childNodes[2].childNodes[0].innerHTML + mkd;
  390. }
  391. }
  392.  
  393. if (isconfig() != -1) {
  394. var usco =
  395. {
  396. "unmarkalert":
  397. {
  398. "name": "取消标记时弹窗确认",
  399. "0": "关闭",
  400. "1": "开启"
  401. },
  402. "autoext":
  403. {
  404. "name": "自动续命",
  405. "0": "关闭",
  406. "1": "开启"
  407. },
  408. "statusny":
  409. {
  410. "name": "Status页面显示是否AC",
  411. "0": "关闭",
  412. "1": "开启"
  413. },
  414. "Blacklist":
  415. {
  416. "name": "Discuss黑名单",
  417. "0": "关闭",
  418. "1": "开启"
  419. },
  420. "AutoUpdateBlacklist":
  421. {
  422. "name": "自动更新Discuss黑名单",
  423. "0": "关闭",
  424. "1": "开启"
  425. }
  426. };
  427. tmpid = 0
  428. txt = "<h3>BZOJ Helper设置</h3>";
  429. document.getElementsByTagName("center")[1 + havenotice].innerHTML += txt;
  430. for (i in usco) {
  431. txt = "<p>";
  432. txt += usco[i]["name"] + ":"
  433. chid = -1
  434. for (j in usco[i]) {
  435. if (j == "name") continue;
  436. txt += "<label for=\"tmprad" + tmpid + "\"><input id=\"tmprad" + tmpid + "\" type=\"radio\" value=\"" + j + "\" name=\"" + i + "\">" + usco[i][j] + "</label>"
  437. if (j == config[i])
  438. chid = tmpid
  439. tmpid++
  440. }
  441. txt += "</p>"
  442. document.getElementsByTagName("center")[1 + havenotice].innerHTML += txt;
  443. document.getElementById("tmprad" + chid).setAttribute("checked", true)
  444. }
  445. document.getElementsByTagName("center")[1 + havenotice].innerHTML += "<p><input id=\"helpersumbit\" type=\"button\" value=\"保存\"/></p>"
  446. document.getElementsByTagName("center")[1 + havenotice].innerHTML += "<span style=\"color:#FF0000\" id=\"savesucci\" hidden=\"true\">保存成功</span>"
  447. document.getElementById("helpersumbit").onclick = function () {
  448. for (i in usco)
  449. config[i] = getradioval(i)
  450. savedata("config", config);
  451. document.getElementById("savesucci").removeAttribute("hidden")
  452. }
  453. }
  454.  
  455. if (isdiscusslist() != -1) {
  456. headerobj = document.getElementsByTagName("center")[1 + havenotice].childNodes[1]
  457. headerobj.childNodes[1].innerHTML += " [<a href=\"javascript:;\" id=\"updateblacklist\">Update Blacklist(Last: " + (new Date(Blacklist["updatetime"] * 1000)).Format("MM-dd hh:mm") + ")</a>]"
  458. document.getElementById("updateblacklist").onclick = function () {
  459. UpdateBlacklistAsync(1)
  460. }
  461. if (config["Blacklist"] == "1") {
  462. tbd = document.getElementsByTagName("tbody")[1]
  463. txt = ""
  464. oo = 0
  465. for (let i of tbd.childNodes) {
  466. if (i.className != "oddrow" && i.className != "evenrow") {
  467. if (i.outerHTML != undefined)
  468. txt += i.outerHTML
  469. continue
  470. }
  471. usern = i.childNodes[3].innerText
  472. titl = i.childNodes[4].innerText
  473. if (Blacklist.user.indexOf(usern) != -1) continue;
  474. if (HaveMatch(titl, Blacklist.title)) continue;
  475. //if(i.className=='oddrow') continue;//check
  476. if (oo == 0) i.className = "evenrow"
  477. else i.className = "oddrow"
  478. txt += i.outerHTML
  479. oo ^= 1
  480. }
  481. tbd.innerHTML = txt
  482. }
  483. }
  484.  
  485. if (isdiscusspage() != -1) {
  486. document.getElementsByTagName("center")[1 + havenotice].childNodes[1].childNodes[1].innerHTML += document.getElementsByTagName("center")[1 + havenotice].childNodes[1].childNodes[5].innerHTML;
  487. }
  488.  
  489. //自动续命
  490. document.getElementsByTagName("center")[0].childNodes[1].innerHTML += "<div class=\"tmp\" style=\"height:0px;width:0px;\"><img id=\"autofre\" src=\"data:image/png;base64,\" style=\"width:0px;height:0px;\"/></div>";
  491. if (config["autoext"] == "1") setInterval(function () { document.getElementById("autofre").src = "https://lydsy.com/JudgeOnline/" }, 600000);
  492. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址