北林OJ

北林OJ专用,替换C++头文件、展示当前题目可查看的答案、提交状态显示与CE原因显示、设置每页展示题目数、展示题目状态

  1. // ==UserScript==
  2. // @name 北林OJ
  3. // @namespace greasyfork.org
  4. // @match https://www.bjfuacm.com
  5. // @match https://www.bjfuacm.com/*
  6. // @grant unsafeWindow
  7. // @grant GM_addStyle
  8. // @grant GM_getValue
  9. // @grant GM_setValue
  10. // @run-at document-start
  11. // @version 1.0
  12. // @author Gwen0x4c3
  13. // @license MIT
  14. // @description 北林OJ专用,替换C++头文件、展示当前题目可查看的答案、提交状态显示与CE原因显示、设置每页展示题目数、展示题目状态
  15. // ==/UserScript==
  16.  
  17. !(function() {
  18. 'use strict';
  19. var $msg = {success:console.log,error:console.log,info:console.log}
  20. let h0x00=setInterval(()=>{
  21. if(document&&document.head&&document.body) {
  22. clearInterval(h0x00)
  23. function useMessage(){function n(n){for(var o=10,e=0;e<f.length;e++){var t=f[e];if(n&&n===t)break;o+=t.clientHeight+20}return o}function o(o){for(var e=0;e<f.length;e++){if(f[e]===o){f.splice(e,1);break}}o.classList.add(a.hide),f.forEach(function(o){o.style.top=n(o)+"px"})}function e(e){function i(){p.removeEventListener("animationend",i),setTimeout(o,x||t.duration||3e3,p)}function s(){"0"===getComputedStyle(p).opacity&&(p.removeEventListener("transitionend",s),p.remove())}var d=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"info",x=arguments[2],p=r.createElement("div");p.className=a.box+" "+d,p.style.top=n()+"px",p.style.zIndex=c,p.innerHTML='\n <span class="'+a.icon+'"></span>\n <span class="'+a.text+'">'+e+"</span>\n ",c++,f.push(p),r.body.appendChild(p),p.addEventListener("animationend",i),p.addEventListener("transitionend",s)}var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=document,i="__"+Math.random().toString(36).slice(2,7),a={box:"msg-box"+i,hide:"hide"+i,text:"msg-text"+i,icon:"msg-icon"+i},s=r.createElement("style");s.textContent=("\n ."+a.box+", ."+a.icon+", ."+a.text+" {\n padding: 0;\n margin: 0;\n box-sizing: border-box;\n }\n ."+a.box+" {\n position: fixed;\n top: 0;\n left: 50%;\n display: flex;\n padding: 12px 16px;\n border-radius: 2px;\n background-color: #fff;\n box-shadow: 0 3px 3px -2px rgba(0,0,0,.2),0 3px 4px 0 rgba(0,0,0,.14),0 1px 8px 0 rgba(0,0,0,.12);\n white-space: nowrap;\n animation: "+a.box+"-move .4s;\n transition: .4s all;\n transform: translate3d(-50%, 0%, 0);\n opacity: 1;\n overflow: hidden;\n }\n ."+a.box+'::after {\n content: "";\n position: absolute;\n left: 0;\n top: 0;\n height: 100%;\n width: 4px;\n }\n @keyframes '+a.box+"-move {\n 0% {\n opacity: 0;\n transform: translate3d(-50%, -100%, 0);\n }\n 100% {\n opacity: 1;\n transform: translate3d(-50%, 0%, 0);\n }\n }\n ."+a.box+"."+a.hide+" {\n opacity: 0;\n /* transform: translate3d(-50%, -100%, 0); */\n transform: translate3d(-50%, -100%, 0) scale(0);\n }\n ."+a.icon+" {\n display: inline-block;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n overflow: hidden;\n margin-right: 6px;\n position: relative;\n }\n ."+a.text+" {\n font-size: 14px;\n line-height: 18px;\n color: #555;\n }\n ."+a.icon+"::after,\n ."+a.icon+'::before {\n position: absolute;\n content: "";\n background-color: #fff;\n }\n .'+a.box+".info ."+a.icon+", ."+a.box+".info::after {\n background-color: #1890ff;\n }\n ."+a.box+".success ."+a.icon+", ."+a.box+".success::after {\n background-color: #52c41a;\n }\n ."+a.box+".warning ."+a.icon+", ."+a.box+".warning::after {\n background-color: #faad14;\n }\n ."+a.box+".error ."+a.icon+", ."+a.box+".error::after {\n background-color: #ff4d4f;\n }\n ."+a.box+".info ."+a.icon+"::after,\n ."+a.box+".warning ."+a.icon+"::after {\n top: 15%;\n left: 50%;\n margin-left: -1px;\n width: 2px;\n height: 2px;\n border-radius: 50%;\n }\n ."+a.box+".info ."+a.icon+"::before,\n ."+a.box+".warning ."+a.icon+"::before {\n top: calc(15% + 4px);\n left: 50%;\n margin-left: -1px;\n width: 2px;\n height: 40%;\n }\n ."+a.box+".error ."+a.icon+"::after, \n ."+a.box+".error ."+a.icon+"::before {\n top: 20%;\n left: 50%;\n width: 2px;\n height: 60%;\n margin-left: -1px;\n border-radius: 1px;\n }\n ."+a.box+".error ."+a.icon+"::after {\n transform: rotate(-45deg);\n }\n ."+a.box+".error ."+a.icon+"::before {\n transform: rotate(45deg);\n }\n ."+a.box+".success ."+a.icon+"::after {\n box-sizing: content-box;\n background-color: transparent;\n border: 2px solid #fff;\n border-left: 0;\n border-top: 0;\n height: 50%;\n left: 35%;\n top: 13%;\n transform: rotate(45deg);\n width: 20%;\n transform-origin: center;\n }\n ").replace(/(\n|\t|\s)*/gi,"$1").replace(/\n|\t|\s(\{|\}|\,|\:|\;)/gi,"$1").replace(/(\{|\}|\,|\:|\;)\s/gi,"$1"),r.head.appendChild(s);var c=t.zIndex||1e4,f=[];return{show:e,info:function(n){e(n,"info")},success:function(n){e(n,"success")},warning:function(n){e(n,"warning")},error:function(n){e(n,"error")}}}
  24. $msg=useMessage();
  25. // $msg.success('脚本开始运行')
  26. }
  27. },100)
  28. function injectCSS() {
  29. GM_addStyle(".error-log{list-style-type:none;padding:0}.error-log li{background-color:#f8d7da;color:#721c24;padding:10px;margin-top:5px;border:1px solid #f5c6cb;border-radius:5px;font-size:14px}");
  30. GM_addStyle('.oj-button{z-index:10000;width:120px;height:30px;line-height:30px;text-align:center;color:black;font-weight:bold;cursor:pointer}.oj-panel{z-index:10000;background:white;position:fixed;left:20px;top:20px;width:390px;border:1px solid #000}.oj-header{position:relative;height:30px;background:rgb(250, 250, 250);cursor:move}.oj-close{position:absolute;right:10px;top:0;font-size:19px;cursor:pointer}.oj-body{min-height:200px;max-height:500px;overflow-y:auto;overflow-x:hidden}.oj-result{padding:10px;transition:.2s;font-size:14px;}.oj-result:hover{background:rgb(240,240,240);}')
  31. GM_addStyle('.ojh{}.ojh-button{}.ojh-save{background:rgb(246,246,246);}.ojh-save-content{display:inline-block;width:90%;height:200px;resize:none;margin:5px auto;vertical-align:top}.ojh-save-button{margin-left:100px}.ojh-body{max-height:500px;padding:10px;overflow-y:auto;background:rgb(240,240,240)}.ojh-file{position:relative;border-bottom:1px solid black;padding: 10px 2px;}.ojh-file-name{}.ojh-file-delete{display:block;position:absolute;right:10px;top:0}.ojh-file-content{display:block;width:100%;height:200px;resize:none;margin:5px auto}.text-button{display:inline-block;text-align:center;color:blue;cursor:pointer}');
  32. }
  33. const status_map={"-2":{name:"Compile Error",short:"CE",color:"orange",type:"warning"},"-1":{name:"Wrong Answer",short:"WA",color:"#f8d7da",type:"error"},0:{name:"Accepted",short:"AC",color:"rgb(232,249,240)",type:"success"},1:{name:"Time Limit Exceeded",short:"TLE",color:"#f8d7da",type:"error"},2:{name:"Time Limit Exceeded",short:"TLE",color:"#f8d7da",type:"error"},3:{name:"Memory Limit Exceeded",short:"MLE",color:"#f8d7da",type:"error"},4:{name:"Runtime Error",short:"RE",color:"#f8d7da",type:"error"},5:{name:"System Error",short:"SE",color:"#f8d7da",type:"error"},6:{name:"Pending",color:"orange",type:"warning"},7:{name:"Judging",color:"blue",type:"info"},8:{name:"Partial Accepted",short:"PAC",color:"blue",type:"info"},9:{name:"Submitting",color:"yellow",type:"warning"}}
  34. const store = {
  35. headers: GM_getValue('oj-headers', []),
  36. pagesize: GM_getValue('oj-pagesize', 20),
  37. difficulty: GM_getValue('oj-difficulty', ""),
  38. problems: {},
  39. hideAC: GM_getValue('oj-hideAC', false),
  40. }
  41. unsafeWindow.fuckingstore = store;
  42. function createElement(tag, clazz, attrs) {
  43. const elem = document.createElement(tag);
  44. elem.className = clazz;
  45. if (attrs) {
  46. for (let key in attrs) {
  47. elem[key] = attrs[key];
  48. }
  49. }
  50. return elem;
  51. }
  52. function sel(selector) {
  53. return document.querySelector(selector);
  54. }
  55. function selall(selector) {
  56. return document.querySelector(selector);
  57. }
  58. let errorLog = null;
  59. function initErrorLog() {
  60. var cardBody = document.querySelectorAll('.ivu-card-body')[1];
  61. if (!cardBody) {
  62. setTimeout(() => {
  63. initErrorLog();
  64. }, 200);
  65. } else {
  66. errorLog = document.createElement('ul');
  67. errorLog.id = 'errorLog';
  68. errorLog.className = 'error-log';
  69. cardBody.appendChild(errorLog);
  70. }
  71. }
  72. function addErrorLog(result, status, info) {
  73. if ([6, 7, 9].indexOf(result) != -1) {
  74. return;
  75. }
  76. var e = document.createElement('li');
  77. let html = "";
  78. html += status.short + "<br/>"
  79. if (result == -2) { // compile error
  80. html += info.err_info;
  81. } else {
  82. html += `耗时: ${info.time_cost} 内存:${submissionMemoryFormat(info.memory_cost)}`
  83. }
  84. e.innerHTML = html;
  85. e.style.backgroundColor = status.color;
  86. errorLog.prepend(e);
  87. }
  88.  
  89. function submissionMemoryFormat(t) {
  90. if (void 0 === t)
  91. return "--";
  92. var e = parseInt(t) / 1048576;
  93. return String(e.toFixed(0)) + "MB"
  94. }
  95. function initHeaderReplace() {
  96. if (!document.querySelector('.ivu-card-body')) {
  97. setTimeout(() => {
  98. initHeaderReplace();
  99. }, 200);
  100. return;
  101. }
  102. const cardBody = document.querySelectorAll('.ivu-card-body')[1];
  103. const ojh = createElement('div', 'ojh');
  104. const body = createElement('div', 'ojh-body', {style: "display:none"})
  105. cardBody.prepend(ojh);
  106. const showButton = createElement('a', 'ojh-button text-button', {textContent: "展示头文件", style: "margin-right:40px;"});
  107. showButton.onclick = e => {
  108. if (showButton.textContent == '展示头文件') {
  109. showButton.textContent = '隐藏头文件';
  110. body.style.display = 'block';
  111. } else {
  112. showButton.textContent = '展示头文件';
  113. body.style.display = 'none';
  114. }
  115. }
  116. ojh.appendChild(showButton);
  117. const uploadButton = createElement('a', 'ojh-button text-button', {textContent: "添加头文件+", style: "margin-right:40px;"});
  118. const save = createElement('div', 'ojh-save', {style: "display:none;"});
  119. save.append(createElement('span', '', {innerText: "引用名称:"}))
  120. const saveInput = createElement('input', '', {style: "width:50%", placeholder: '代码中#include "../h/header.h",就填../h/header.h'});
  121. save.append(saveInput);
  122. save.append(createElement('br'))
  123. save.append(createElement('span', '', {innerText: "文件内容:"}))
  124. const saveArea = createElement('textarea', 'ojh-save-content');
  125. save.append(saveArea);
  126. const saveButton = createElement('button', 'ojh-save-button', {textContent: "保存"});
  127. uploadButton.onclick = e => {
  128. if (uploadButton.textContent == '添加头文件+') {
  129. uploadButton.textContent = '添加头文件-';
  130. save.style.display = 'block';
  131. } else {
  132. uploadButton.textContent = '添加头文件+';
  133. save.style.display = 'none';
  134. }
  135. }
  136. saveButton.onclick = e => {
  137. console.log(saveInput.value, saveArea.value)
  138. if (!saveInput.value) {
  139. $msg.error("引用名称没填");
  140. return;
  141. }
  142. if (!saveArea.value) {
  143. $msg.error("文件内容为空");
  144. return;
  145. }
  146. saveHeader(body, saveInput.value, saveArea.value);
  147. saveInput.value = saveArea.value = ""
  148. }
  149. const replaceButton = createElement('button', 'ojh-button', {textContent: "替换内容"});
  150. replaceButton.onclick = e => {
  151. $msg.info("开始替换代码中的头文件")
  152. let data = document.querySelector('.flex-container').__vue__.$data;
  153. let code = data.code;
  154. const regex = /#include "(.*?)"/g;
  155. while (true) {
  156. console.log("yici")
  157. let match;
  158. const headers = [];
  159. while ((match = regex.exec(code)) !== null) {
  160. headers.push(match[1]);
  161. }
  162. // 找是否存在header
  163. let find = false;
  164. for (let i = 0; i < headers.length; i++) {
  165. console.log("找是否匹配" + headers[i]);
  166. for (let storedHeader of store.headers) {
  167. if (headers[i] == storedHeader.name) {
  168. const escapedHeader = storedHeader.name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  169. const regex = new RegExp(`#include "${escapedHeader}"`, 'g');
  170. let content = '// ' + storedHeader.name + "\n";
  171. content += storedHeader.content + "\n";
  172. code = code.replace(regex, content);
  173. find = true;
  174. break;
  175. }
  176. }
  177. }
  178. if (!find) {
  179. if (headers.length != 0) {
  180. $msg.info("未找到头文件:" + JSON.stringify(headers))
  181. }
  182. break;
  183. }
  184. }
  185. data.code = code;
  186. $msg.success("替换完成")
  187. }
  188. save.appendChild(saveButton);
  189. ojh.appendChild(uploadButton);
  190. ojh.appendChild(replaceButton);
  191. ojh.appendChild(save);
  192.  
  193. ojh.append(body);
  194. showHeaders(body)
  195. }
  196. function showHeader(body, header) {
  197. const file = createElement('div', 'ojh-file', {id: "ojh-file-" + header.name});
  198. const name = createElement('span', 'ojh-file-name text-button', {innerText: header.name});
  199. const wrapper = createElement('div', 'ojh-file-wrapper', {style: "display: none;"})
  200. name.onclick = e => {
  201. if (wrapper.style.display == 'none') {
  202. wrapper.style.display = 'block';
  203. } else {
  204. wrapper.style.display = 'none';
  205. }
  206. }
  207. const deleteButton = createElement('a', 'ojh-file-delete text-button', {textContent: "删除"})
  208. deleteButton.onclick = e => {
  209. if (confirm("是否删除?")) {
  210. deleteHeader(header.name)
  211. document.getElementById('ojh-file-' + header.name)?.remove();
  212. }
  213. }
  214. file.append(name);
  215. file.append(deleteButton);
  216. const content = createElement('textarea', 'ojh-file-content', {value: header.content})
  217. const save = createElement('button', '', {textContent: "保存"});
  218. save.onclick = e => {
  219. saveHeader(body, header.name, content.value)
  220. }
  221. wrapper.append(content);
  222. wrapper.append(save);
  223. file.append(wrapper)
  224. body.append(file);
  225. }
  226. function showHeaders(body) {
  227. for (let header of store.headers) {
  228. showHeader(body, header);
  229. }
  230. }
  231. function saveHeader(body, name, content) {
  232. let headerElem = document.getElementById('ojh-file-' + name);
  233. if (!headerElem) {
  234. showHeader(body, {name, content})
  235. }
  236. for (let header of store.headers) { // 找是否有重复的
  237. if (header.name == name) {
  238. header.content = content;
  239. $msg.success("修改成功")
  240. GM_setValue('oj-headers', store.headers);
  241. return;
  242. }
  243. }
  244. store.headers.push({name, content});
  245. GM_setValue('oj-headers', store.headers);
  246. $msg.success("添加成功")
  247. }
  248. function deleteHeader(name) {
  249. console.log("删除头文件" + name);
  250. for (let i = 0; i < store.headers.length; i++) {
  251. if (store.headers[i].name == name) {
  252. store.headers.splice(i, 1);
  253. break;
  254. }
  255. }
  256. GM_setValue('oj-headers', store.headers);
  257. $msg.success("删除成功")
  258. }
  259.  
  260. function initAnswerPanel() {
  261. if (!document.querySelector('.oj-menu')) {
  262. setTimeout(() => {
  263. initAnswerPanel();
  264. }, 200);
  265. return;
  266. }
  267. if (document.querySelector('.oj-panel')) {
  268. return;
  269. }
  270. const panel = createElement('div', 'oj-panel')
  271. const header = createElement('div', 'oj-header')
  272. const close = createElement('div', 'oj-close')
  273. close.innerText = '×'
  274. const body = createElement('div', 'oj-body')
  275. header.appendChild(close)
  276. panel.appendChild(header)
  277. panel.appendChild(body)
  278. document.body.appendChild(panel)
  279. let lastX = GM_getValue('box_last_x', 100)
  280. let lastY = GM_getValue('box_last_y', 100)
  281. panel.style.left = lastX + 'px'
  282. panel.style.top = lastY + 'px'
  283. panel.style.display = 'none'
  284. header.addEventListener('mousedown', makeDraggableFunction(panel, false, null, () => {
  285. GM_setValue('box_last_x', parseInt(panel.style.left))
  286. GM_setValue('box_last_y', parseInt(panel.style.top))
  287. }), false)
  288. const showButton = createElement('span', 'oj-button ivu-menu-item')
  289. showButton.innerText = '看可见答案'
  290. document.querySelector('.oj-menu').appendChild(showButton)
  291. showButton.addEventListener('click', e => {
  292. showButton.style.display = 'none'
  293. panel.style.display = 'block'
  294. body.innerHTML = ''
  295. getAnswers()
  296. })
  297. close.addEventListener('click', e => {
  298. panel.style.display = 'none'
  299. showButton.style.display = 'block'
  300. stop = true;
  301. })
  302. }
  303. function makeDraggableFunction(elem, allowMoveOut, exec, callback) {
  304. let handleMouseDown = function (event) {
  305. let offsetX = parseInt(elem.style.left)
  306. let offsetY = parseInt(elem.style.top)
  307. let innerX = event.clientX - offsetX
  308. let innerY = event.clientY - offsetY
  309. if (!!exec) {
  310. exec()
  311. }
  312. document.onmousemove = function (event) {
  313. elem.style.left = event.clientX - innerX + 'px'
  314. elem.style.top = event.clientY - innerY + 'px'
  315. if (!allowMoveOut) {
  316. if (parseInt(elem.style.left) <= 0) {
  317. elem.style.left = '0px'
  318. }
  319. if (parseInt(elem.style.top) <= 0) {
  320. elem.style.top = '0px'
  321. }
  322. if (
  323. parseInt(elem.style.left) >=
  324. window.innerWidth - parseInt(elem.style.width)
  325. ) {
  326. elem.style.left =
  327. window.innerWidth - parseInt(elem.style.width) + 'px'
  328. }
  329. if (
  330. parseInt(elem.style.top) >=
  331. window.innerHeight - parseInt(elem.style.height)
  332. ) {
  333. elem.style.top = window.innerHeight - parseInt(elem.style.height) + 'px'
  334. }
  335. }
  336. }
  337. document.onmouseup = function () {
  338. document.onmousemove = null
  339. document.onmouseup = null
  340. if (!!callback) {
  341. callback()
  342. }
  343. }
  344. }
  345. return handleMouseDown
  346. }
  347. let stop = false;
  348. function getProblemId() {
  349. let url = location.href;
  350. if (url.indexOf('/problem') != -1) {
  351. url = url.substring(url.lastIndexOf('/') + 1);
  352. return parseInt(url);
  353. }
  354. return null;
  355. }
  356. function getAnswers() {
  357. let problemId = getProblemId();
  358. if (!problemId) {
  359. alert("未在答题界面!")
  360. return;
  361. }
  362. stop = false;
  363. let total = -1;
  364. getList(problemId, 1);
  365. }
  366. function getList(problemId, page) {
  367. const offset = (page - 1) * 100;
  368. fetch(`https://www.bjfuacm.com/api/submissions?myself=0&result=0&username=&page=${page}&problem_id=${problemId}&limit=100&offset=${offset}`, {
  369. "headers": {
  370. "accept-language": "zh-CN,zh;q=0.9",
  371. "content-type": "application/json;charset=utf-8",
  372. },
  373. "body": null,
  374. "method": "GET",
  375. }).then(res => res.json()).then(res => {
  376. // console.log(res)
  377. const {results, total} = res.data;
  378. let html = ''
  379. for (let result of results) {
  380. if (result.show_link) {
  381. const info = result.statistic_info;
  382. html += `<div class="oj-result">
  383. <a href="https://www.bjfuacm.com/status/${result.id}" target="_blank">查看答案</a>
  384. <span>耗时${info.time_cost}MS 内存${submissionMemoryFormat(info.memory_cost)}
  385. 作者<a href="https://www.bjfuacm.com/user-home?username=${result.username}" target="_blank">${result.username}</a></span></div>`
  386. }
  387. }
  388. document.querySelector('.oj-body').innerHTML += html;
  389. if (!stop && offset < total) {
  390. getList(problemId, page + 1);
  391. } else {
  392. document.querySelector('.oj-body').innerHTML += "<p style='text-align:center;'>—————— 已加载全部 ——————</p>";
  393. }
  394. }).catch(err => {
  395. console.error(err);
  396. alert("ERROR: " + err)
  397. });
  398. }
  399. /**
  400. * 为list添加每页展示数量的选项
  401. */
  402. function initPageOption(parent, onchange) {
  403. if (!sel('.content-app')) {
  404. setTimeout(initPageOption, 200);
  405. return;
  406. }
  407. setTimeout(() => {
  408. let vue = sel('.content-app').children[0].__vue__;
  409. console.log(vue)
  410. if (parent) {
  411. vue = vue.$parent;
  412. }
  413. vue.limit = store.pagesize;
  414. if (onchange) {
  415. onchange(vue, store.pagesize)
  416. }
  417. const filter = sel('.filter');
  418. const pageSelect = createElement('select', '', {style: "margin-right:10px;"})
  419. for (let pagesize of [10, 20, 30, 50, 100]) {
  420. const option = createElement('option', '', {label: `${pagesize}个/页`, textContent: `${pagesize}个/页`, value: pagesize});
  421. pageSelect.append(option);
  422. if (vue.limit == pagesize) {
  423. pageSelect.value = pagesize;
  424. }
  425. }
  426. pageSelect.onchange = e => {
  427. if (onchange) {
  428. onchange(vue, pageSelect.value);
  429. }
  430. store.pagesize = pageSelect.value;
  431. GM_setValue('oj-pagesize', store.pagesize);
  432. }
  433. filter.prepend(pageSelect);
  434. if (parent) { // if in problem list page
  435. const hideACLabel = createElement('label', '', {style: 'margin-right:10px', innerText: '隐藏已完成'});
  436. const hideACCheck = createElement('input', '', {type: 'checkbox', checked: store.hideAC});
  437. hideACCheck.onchange = e => {
  438. store.hideAC = hideACCheck.checked;
  439. GM_setValue('oj-hideAC', store.hideAC);
  440. onchange(vue, pageSelect.value);
  441. }
  442. hideACLabel.append(hideACCheck);
  443. filter.prepend(hideACLabel);
  444. }
  445. }, 200)
  446. }
  447. function hookRequest() {
  448. const originalOpen = XMLHttpRequest.prototype.open;
  449. XMLHttpRequest.prototype.open = function(method, url) {
  450. if (url.indexOf('/api/submission?id=') != -1) {
  451. this.addEventListener('readystatechange', function() {
  452. if (this.readyState == 4) {
  453. const res = JSON.parse(this.responseText);
  454. const result = res.data.result;
  455. const status = status_map[result]
  456. console.log(res, status)
  457. if (!res.data.statistic_info) {
  458. return;
  459. }
  460. const info = res.data.statistic_info;
  461. addErrorLog(result, status, info);
  462. store.problems[res.data.problem] = {status: result};
  463. }
  464. })
  465. } else if (url.indexOf('/api/profile') != -1) {
  466. this.addEventListener('readystatechange', function() {
  467. if (this.readyState == 4) {
  468. const res = JSON.parse(this.responseText);
  469. store.problems = res.data.acm_problems_status.problems;
  470. console.log('SOLVED: ', store.problems)
  471. }
  472. })
  473. } else if (url.indexOf('/api/problem') != -1) {
  474. this.addEventListener('readystatechange', function() {
  475. if (this.readyState == 4) {
  476. const res = JSON.parse(this.responseText);
  477. const list = res.data.results;
  478. for (let i = 0; i < list.length; i++) {
  479. const problem = list[i];
  480. let status = store.problems[problem.id]
  481. if (status) {
  482. if (status.status == 0) {
  483. if (store.hideAC) {
  484. list.splice(i, 1);
  485. i--;
  486. } else {
  487. problem.title = '✔️ ' + problem.title;
  488. }
  489. } else {
  490. problem.title = '❌ ' + problem.title;
  491. }
  492. }
  493. }
  494. Object.defineProperty(this, 'responseText', {writable: true})
  495. this.responseText = JSON.stringify(res);
  496. }
  497. })
  498. }
  499. originalOpen.apply(this, arguments);
  500. }
  501. }
  502. function urlContains(url, targets) {
  503. for (let target of targets) {
  504. if (url.indexOf(target) != -1) {
  505. return true;
  506. }
  507. }
  508. return false;
  509. }
  510. let lastPath = "DAMNSONWHEREDYOUFINDTHAT";
  511. setInterval(() => {
  512. if (location.pathname != lastPath) {
  513. lastPath = location.pathname;
  514. if (lastPath.indexOf('/problem/') != -1) {
  515. injectCSS();
  516. initErrorLog();
  517. initAnswerPanel();
  518. initHeaderReplace();
  519. } else if (['/problems', '/structure', '/started'].indexOf(lastPath) != -1) {
  520. initPageOption(true, (vue, pagesize) => {
  521. vue.limit = pagesize;
  522. vue.query.page = 1;
  523. if (!vue.query.difficulty || vue.query.difficulty == '') {
  524. vue.query.difficulty = store.difficulty;
  525. } else {
  526. store.difficulty = vue.query.difficulty;
  527. GM_setValue('oj-difficulty', store.difficulty);
  528. }
  529. vue.getProblemList();
  530. });
  531. } else if (lastPath == '/status') {
  532. initPageOption(false, (vue, pagesize) => {
  533. vue.limit = pagesize;
  534. vue.page = 1;
  535. vue.getSubmissions();
  536. });
  537. }
  538. console.log("path切换为" + lastPath)
  539. }
  540. }, 500);
  541. hookRequest();
  542. })()