Ex124OJ

Extend 124OJ!

当前为 2022-12-17 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Ex124OJ
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.10.8
  5. // @description Extend 124OJ!
  6. // @author Sukwants
  7. // @license MIT
  8. // @match http://124.221.194.184
  9. // @match http://124.221.194.184/*
  10. // @icon https://www.imageoss.com/images/2022/11/29/ex124OJba563861978a769d.png
  11. // @grant GM_addStyle
  12. // @grant GM_xmlhttpRequest
  13. // @grant GM_listValues
  14. // @grant GM_getValue
  15. // @grant GM_setValue
  16. // @grant GM_deleteValue
  17. // @connect ex124oj.netlify.app
  18. // ==/UserScript==
  19.  
  20.  
  21. const Version = '0.10.8';
  22.  
  23. const HomepageRegExp = /^http:\/\/124.221.194.184(\/){0,1}(\?.*){0,1}$/;
  24. function isHomepage() {
  25. return HomepageRegExp.test(window.location.href);
  26. }
  27. const submissionRegExp = /^http:\/\/124.221.194.184\/submission\/\d{1,}/;
  28. function isSubmission() {
  29. return submissionRegExp.test(window.location.href);
  30. }
  31. const ProblemRegExp = /^http:\/\/124.221.194.184.*\/problem\/(\d{1,})(\?.*){0,1}$/;
  32. function isProblem() {
  33. return ProblemRegExp.test(window.location.href);
  34. }
  35. const UserProfileRegExp = /^http:\/\/124.221.194.184\/user\/profile\/.{1,}/;
  36. function isUserProfile() {
  37. return UserProfileRegExp.test(window.location.href);
  38. }
  39. const BlogRegExp = /^http:\/\/124.221.194.184\/blog\/.{1,}/;
  40. function isBlog() {
  41. return BlogRegExp.test(window.location.href);
  42. }
  43.  
  44. var BackgroundImage;
  45. var SiteIconImage;
  46. var SiteIconSmallImage;
  47. var Academic;
  48. function resetVariables() {
  49. BackgroundImage = GM_getValue('BackgroundImage') != undefined ? GM_getValue('BackgroundImage') : '';
  50. SiteIconImage = GM_getValue('SiteIconImage') != undefined ? GM_getValue('SiteIconImage') : 'https://www.imageoss.com/images/2022/11/29/ex124OJba563861978a769d.png';
  51. SiteIconSmallImage = GM_getValue('SiteIconSmallImage') != undefined ? GM_getValue('SiteIconSmallImage') : 'https://www.imageoss.com/images/2022/12/13/icon1ca65ac1e49f8ec3c.png';
  52. Academic = GM_getValue('Academic') != undefined ? GM_getValue('Academic') : false;
  53. }
  54. resetVariables();
  55.  
  56. var NameColorList = GM_getValue('NameColorList') != undefined ? GM_getValue('NameColorList') : {};
  57. var CCFBadgeList = GM_getValue('CCFBadgeList') != undefined ? GM_getValue('CCFBadgeList') : {};
  58. var TagBadgeList = GM_getValue('TagBadgeList') != undefined ? GM_getValue('TagBadgeList') : {};
  59. GM_xmlhttpRequest({
  60. method: "GET",
  61. url: "https://ex124oj.netlify.app/public/variables.json",
  62. onload: function(data) {
  63. var variables = JSON.parse(data.responseText);
  64. NameColorList = variables.NameColorList;
  65. GM_setValue('NameColorList', NameColorList);
  66. CCFBadgeList = variables.CCFBadgeList;
  67. GM_setValue('CCFBadgeList', CCFBadgeList);
  68. TagBadgeList = variables.TagBadgeList;
  69. GM_setValue('TagBadgeList', TagBadgeList);
  70. FunctionsWithUniversalVariables();
  71. }
  72. });
  73.  
  74. (function() {
  75. 'use strict';
  76. Settings();
  77. FontAwesome();
  78. Background();
  79. changeIcon();
  80. DiscussionCard();
  81. CodeBlock();
  82. TableStyle();
  83. RandomProblem();
  84. if (isHomepage()) exAnnouncements();
  85. if (isSubmission()) SubmissionCard();
  86. if (isProblem()) downloadData();
  87. if (isUserProfile() || isBlog()) changeGravatarURL();
  88. FunctionsWithUniversalVariables();
  89. })();
  90.  
  91. function FunctionsWithUniversalVariables() {
  92. clearNameStyle();
  93. NameColor();
  94. NameBadge();
  95. }
  96.  
  97. function Settings() {
  98. GM_addStyle('\
  99. .settings-overlay {\
  100. position: fixed;\
  101. height: 100%;\
  102. width: 100%;\
  103. transition: visibility 0.4s, background 0.4s;\
  104. top: 0;\
  105. left: 0;\
  106. visibility: hidden;\
  107. z-index: 229;\
  108. }\
  109. .settings-popup-active .settings-overlay {\
  110. background: rgb(0,0,0,.3);\
  111. visibility: visible;\
  112. }\
  113. .settings-popup {\
  114. width: 60%;\
  115. position: relative;\
  116. transform: translate(-50%, -50%);\
  117. top: 50%;\
  118. left: 50%;\
  119. visibility: hidden;\
  120. border-radius: .5rem;\
  121. padding: 20px 20px;\
  122. }\
  123. .settings-popup-active .settings-overlay .settings-popup {\
  124. background: #ffffff;\
  125. visibility: visible;\
  126. }\
  127. .settings-popup .row {\
  128. padding: 0 30px 30px;\
  129. }\
  130. .settings-titlebar {\
  131. padding: 10px 20px 30px 20px !important;\
  132. }\
  133. .settings-titlebar h4 {\
  134. position: relative;\
  135. top: 50%;\
  136. left: 0;\
  137. transform: translate(0, -50%);\
  138. }\
  139. .settings-footerbar {\
  140. height: 60px;\
  141. padding: 20px 20px;\
  142. }\
  143. ');
  144. var HomepageEntrance = document.createElement('li');
  145. document.getElementsByClassName('container')[0].children[0].children[0].children[0].before(HomepageEntrance);
  146. HomepageEntrance.setAttribute('class', 'nav-item');
  147. HomepageEntrance.innerHTML = '<span style="padding: 0.5rem 1rem; cursor:pointer"><span style="background-color: #28adca;padding:0.2em 0.6em;border-radius: 1em;color:#fff;font-size: 0.7em;font-weight:bold;display:inline-block;position: relative;top: 50%;transform: translate(0,-50%);">Ex124OJ</span></span>';
  148. HomepageEntrance.onclick = function() {
  149. document.body.setAttribute('class', 'settings-popup-active');
  150. }
  151. var SettingsOverlay = document.createElement('div');
  152. document.body.children[0].before(SettingsOverlay);
  153. SettingsOverlay.setAttribute('class', 'settings-overlay');
  154. var SettingsPopup = document.createElement('div');
  155. SettingsOverlay.appendChild(SettingsPopup);
  156. SettingsPopup.setAttribute('class', 'settings-popup');
  157. var SettingsTitlebar = document.createElement('div');
  158. SettingsPopup.appendChild(SettingsTitlebar);
  159. SettingsTitlebar.setAttribute('class', 'row settings-titlebar');
  160. SettingsTitlebar.innerHTML = '<h3 style="width:100%;height:3.5rem"><img src="https://ex124oj.netlify.app/images/icon.png" style="height:3.5rem;width:3.5rem;margin-right:10px"><span style="vertical-align:middle"> Ex124OJ 控制面板</span> <span style="vertical-align:middle;cursor:pointer;margin:0 10px" onclick="window.open(\'https://ex124oj.netlify.app/\');"><span style="height:1.75rem;line-height:3.5rem;vertical-align:middle;padding:0 .5rem;background-color:#28adca;border-radius:1em;color:#fff;font-size:1.2rem;font-weight:bold">Ex124OJ</span></span><span style="color:#7f7f7f;line-height:3.5rem;vertical-align:middle;font-size:1.2rem">' + Version + '</span></h3>';
  161. var SettingsCloseButton = document.createElement('span');
  162. SettingsPopup.appendChild(SettingsCloseButton);
  163. SettingsCloseButton.setAttribute('style', 'position: fixed;right: 20px;top:20px;cursor: pointer');
  164. SettingsCloseButton.setAttribute('onclick', 'document.body.setAttribute(\'class\', \'\');');
  165. SettingsCloseButton.innerHTML = '<h4><i class="fa fa-xmark"></i></h4>';
  166.  
  167. var background = document.createElement('div');
  168. SettingsPopup.appendChild(background);
  169. background.setAttribute('class', 'row');
  170. var backgroundImageLabel = document.createElement('strong');
  171. background.appendChild(backgroundImageLabel);
  172. backgroundImageLabel.setAttribute('style', 'font-size: 1.25em');
  173. backgroundImageLabel.innerHTML = '背景图片&emsp;&emsp;&emsp;&emsp;';
  174. var backgroundImageInput = document.createElement('input');
  175. background.appendChild(backgroundImageInput);
  176. backgroundImageInput.setAttribute('style', 'flex-grow: 1; height: 2em; width: initial');
  177. backgroundImageInput.setAttribute('class', 'form-control');
  178.  
  179. var siteIcon = document.createElement('div');
  180. SettingsPopup.appendChild(siteIcon);
  181. siteIcon.setAttribute('class', 'row');
  182. var siteIconImageLabel = document.createElement('strong');
  183. siteIcon.appendChild(siteIconImageLabel);
  184. siteIconImageLabel.setAttribute('style', 'font-size: 1.25em');
  185. siteIconImageLabel.innerHTML = '网站图标&emsp;&emsp;&emsp;&emsp;';
  186. var siteIconImageInput = document.createElement('input');
  187. siteIcon.appendChild(siteIconImageInput);
  188. siteIconImageInput.setAttribute('style', 'flex-grow: 1; height: 2em; width: initial');
  189. siteIconImageInput.setAttribute('class', 'form-control');
  190.  
  191. var siteIconSmall = document.createElement('div');
  192. SettingsPopup.appendChild(siteIconSmall);
  193. siteIconSmall.setAttribute('class', 'row');
  194. var siteIconSmallImageLabel = document.createElement('strong');
  195. siteIconSmall.appendChild(siteIconSmallImageLabel);
  196. siteIconSmallImageLabel.setAttribute('style', 'font-size: 1.25em');
  197. siteIconSmallImageLabel.innerHTML = '网站图标(小)&emsp;';
  198. var siteIconSmallImageInput = document.createElement('input');
  199. siteIconSmall.appendChild(siteIconSmallImageInput);
  200. siteIconSmallImageInput.setAttribute('style', 'flex-grow: 1; height: 2em; width: initial');
  201. siteIconSmallImageInput.setAttribute('class', 'form-control');
  202.  
  203. var academic = document.createElement('div');
  204. SettingsPopup.appendChild(academic);
  205. academic.setAttribute('class', 'row');
  206. academic.setAttribute('style', 'line-height: 2.5em;vertical-align: middle');
  207. var academicLabel = document.createElement('strong');
  208. academic.appendChild(academicLabel);
  209. academicLabel.setAttribute('style', 'font-size: 1.25em');
  210. academicLabel.innerHTML = '学术模式&emsp;&emsp;&emsp;&emsp;';
  211. var academicOff = document.createElement('div');
  212. academic.appendChild(academicOff);
  213. academicOff.innerHTML = '<input type="radio" id="AcademicOff"> 关闭&emsp;';
  214. var academicOn = document.createElement('div');
  215. academic.appendChild(academicOn);
  216. academicOn.innerHTML = '<input type="radio" id="AcademicOn"> 开启&emsp;';
  217. document.getElementById('AcademicOff').onclick = function() {
  218. document.getElementById('AcademicOn').checked = false;
  219. }
  220. document.getElementById('AcademicOn').onclick = function() {
  221. document.getElementById('AcademicOff').checked = false;
  222. }
  223.  
  224. function resetModified() {
  225. backgroundImageInput.value = BackgroundImage;
  226. siteIconImageInput.value = SiteIconImage;
  227. siteIconSmallImageInput.value = SiteIconSmallImage;
  228. if (Academic != true) {
  229. document.getElementById('AcademicOff').checked = true;
  230. document.getElementById('AcademicOn').checked = false;
  231. }
  232. else {
  233. document.getElementById('AcademicOff').checked = false;
  234. document.getElementById('AcademicOn').checked = true;
  235. }
  236. }
  237. resetModified();
  238.  
  239. var FooterRow = document.createElement('div');
  240. FooterRow.setAttribute('class', 'settings-footerbar');
  241. SettingsPopup.appendChild(FooterRow);
  242. var Ok = document.createElement('button');
  243. FooterRow.appendChild(Ok);
  244. Ok.setAttribute('class', 'btn btn-search btn-outline-primary float-right');
  245. Ok.innerHTML = '保存';
  246. Ok.onclick = function() {
  247. GM_setValue('BackgroundImage', backgroundImageInput.value);
  248. GM_setValue('SiteIconImage', siteIconImageInput.value);
  249. GM_setValue('SiteIconSmallImage', siteIconSmallImageInput.value);
  250. GM_setValue('Academic', document.getElementById('AcademicOn').checked);
  251. resetVariables();
  252. window.location.href = window.location.href;
  253. };
  254. var Clear = document.createElement('button');
  255. FooterRow.appendChild(Clear);
  256. Clear.setAttribute('class', 'btn btn-search btn-outline-primary float-right');
  257. Clear.innerHTML = '恢复默认';
  258. Clear.onclick = function() {
  259. var values = GM_listValues();
  260. for (var value in values) {
  261. GM_deleteValue(values[value]);
  262. }
  263. resetVariables();
  264. resetModified();
  265. window.location.href = window.location.href;
  266. }
  267. }
  268.  
  269. function FontAwesome() {
  270. var fa = document.createElement('link');
  271. fa.setAttribute('href', 'https://cdn.bootcdn.net/ajax/libs/font-awesome/6.2.1/css/fontawesome.css');
  272. fa.setAttribute('rel', 'stylesheet');
  273. document.head.appendChild(fa);
  274. var fab = document.createElement('link');
  275. fab.setAttribute('href', 'https://cdn.bootcdn.net/ajax/libs/font-awesome/6.2.1/css/brands.css');
  276. fab.setAttribute('rel', 'stylesheet');
  277. document.head.appendChild(fab);
  278. var fas = document.createElement('link');
  279. fas.setAttribute('href', 'https://cdn.bootcdn.net/ajax/libs/font-awesome/6.2.1/css/solid.css');
  280. fas.setAttribute('rel', 'stylesheet');
  281. document.head.appendChild(fas);
  282. }
  283.  
  284. function Background() {
  285. if (BackgroundImage) {
  286. document.getElementsByClassName('navbar-brand')[0].innerHTML = '<img src="http://124.221.194.184/images/logo_small.png" alt="Logo" class="img-rounded" style="width:39px; height:39px;">';
  287. document.getElementsByClassName('container')[0].children[0].children[1].innerHTML = document.getElementsByClassName('container')[0].children[0].children[1].innerHTML.match(/(.*> ){0,1}(.*)/)[2];
  288. GM_addStyle('\
  289. body {\
  290. background: url("' + BackgroundImage + '");\
  291. background-repeat: no-repeat;\
  292. background-attachment: fixed;\
  293. background-position: 50% 50%;\
  294. background-size: cover;\
  295. }\
  296. .uoj-content {\
  297. background-color: #fff;\
  298. margin: 16px -16px;\
  299. padding: 16px 16px;\
  300. opacity: 0.85;\
  301. border-radius: 8px;\
  302. }\
  303. .navbar {\
  304. margin: 16px -16px;\
  305. padding: 8px 16px;\
  306. opacity: 0.85;\
  307. border-radius: 8px;\
  308. }\
  309. .giscus {\
  310. opacity: 0.85;\
  311. }');
  312. }
  313. }
  314.  
  315. function getIcon() {
  316. if (SiteIconImage) return SiteIconImage;
  317. else return '/images/logo.png';
  318. }
  319. function getIconSmall() {
  320. if (SiteIconSmallImage) return SiteIconSmallImage;
  321. else return getIcon();
  322. }
  323. function changeIcon() {
  324. const LogoURLRegExp = /^.*\/images\/logo(_small){0,1}.png$/;
  325. var Links = document.getElementsByTagName('link');
  326. for (var link in Links) {
  327. if (Links[link] && Links[link].nodeType && Links[link].getAttribute('rel') == 'shortcut icon') {
  328. Links[link].setAttribute('href', getIconSmall());
  329. }
  330. }
  331. var Icons = document.getElementsByTagName('img');
  332. for (var icon in Icons) {
  333. if (Icons[icon] && Icons[icon].nodeType && LogoURLRegExp.test(Icons[icon].getAttribute('src'))) {
  334. if (!Icons[icon].getAttribute('style')) {
  335. Icons[icon].setAttribute('src', getIcon());
  336. Icons[icon].setAttribute('style', 'width:100%;height:auto;object-fit:cover');
  337. }
  338. else {
  339. Icons[icon].setAttribute('src', getIconSmall());
  340. }
  341. }
  342. }
  343. }
  344.  
  345. function exAnnouncements() {
  346. const PostsExp = /^[\s\S]*<div id="archives">([\s\S]*)<script>([\s\S]*?)<\/script>([\s\S]*?)<\/div>\s*?<footer id="footer">[\s\S]*$/;
  347. const WrittenByExp = /^by (.*)$/;
  348. const DateTimeExp = /^(.*?) .*$/;
  349. if (document.getElementsByClassName('uoj-content')[0].children[0].children[0].children[0]) {
  350. GM_xmlhttpRequest({
  351. method: "GET",
  352. url: "https://ex124oj.netlify.app/categories/announcements/",
  353. onload: function(data) {
  354. var Announcements = document.getElementsByClassName('uoj-content')[0].children[0].children[0].children[0].children[0].children[0];
  355. Announcements.children[0].children[0].innerHTML = '<th style="width:30%">公告</th><th style="width:10%"></th><th style="width:10%"></th><th style="width:30%">Ex 公告</th><th style="width:10%"></th><th style="width:10%"></th>';
  356. var trs = Announcements.children[1].getElementsByTagName('tr');
  357. for (var tr = 0; tr < trs.length - 1; ++tr) {
  358. if (trs[tr].innerHTML) {
  359. trs[tr].innerHTML = (trs[tr].children.length > 2 ? trs[tr].innerHTML : '<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>') + '<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>';
  360. if (WrittenByExp.test(trs[tr].children[1] && trs[tr].children[1].innerHTML)) {
  361. trs[tr].children[1].innerHTML = trs[tr].children[1].innerHTML.match(WrittenByExp)[1];
  362. }
  363. if (DateTimeExp.test(trs[tr].children[2] && trs[tr].children[2].innerHTML)) {
  364. trs[tr].children[2].innerHTML = '<small>' + trs[tr].children[2].textContent.match(DateTimeExp)[1] + '</small>';
  365. }
  366. }
  367. }
  368. Announcements.children[1].children[Announcements.children[1].children.length - 1].innerHTML = '<td class="text-right" colspan="3"><a href="/announcements">所有公告……</a></td><td class="text-right" colspan="3"><a href="https://ex124oj.netlify.app/categories/announcements/">所有公告……</a></td>';
  369. var Posts = document.createElement('div');
  370. Posts.innerHTML = data.responseText.match(PostsExp)[1];
  371. for (var i = 0; i < Posts.children.length && i < 5; ++i) {
  372. Announcements.children[1].children[i].children[3].innerHTML = '<a href="https://ex124oj.netlify.app' + Posts.children[i].children[0].children[0].children[1].getAttribute('href') + '">' + Posts.children[i].children[0].children[0].children[1].children[0].innerHTML.match(/^\s*(.*?)\s*$/)[1] + '</a>';
  373. Announcements.children[1].children[i].children[4].innerHTML = '<a class="uoj-username" href="https://ex124oj.netlify.app" style="color:rgb(40,173,202)">Ex124OJ</a>';
  374. var Date = Posts.children[i].children[0].children[0].children[0].innerHTML.match(/^(\d*)\/(\d*)\/(\d*)$/);
  375. if (Date[2].length < 2) Date[2] = '0' + Date[2];
  376. if (Date[3].length < 2) Date[3] = '0' + Date[3];
  377. Announcements.children[1].children[i].children[5].innerHTML = '<small>' + Date[1] + '-' + Date[2] + '-' + Date[3] + '</small>'
  378. }
  379. }
  380. });
  381. }
  382. }
  383.  
  384. function RandomProblem() {
  385. var SearchBox = document.getElementById('form-search-problem')
  386. if (SearchBox) {
  387. var RandomButton = document.createElement('div');
  388. RandomButton.setAttribute('class', 'input-group-append');
  389. RandomButton.innerHTML = '<button class="btn btn-search btn-outline-primary" onclick="randomProblem();">随机跳题</button>';
  390. var RandomScript = document.createElement('script');
  391. RandomScript.innerHTML = '\
  392. var randomProblemId, randomProblemResult;\
  393. function randomProblem() {\
  394. randomProblemId = Math.ceil(Math.random() * 3000);\
  395. randomProblemResult = ($.get(\'/problem/\' + randomProblemId));\
  396. turntoProblem();\
  397. }\
  398. function turntoProblem() {\
  399. console.log(randomProblemResult.status);\
  400. if (randomProblemResult.status) {\
  401. if (randomProblemResult.status == 200) {\
  402. window.location.href = \'http://124.221.194.184/problem/\' + randomProblemId;\
  403. }\
  404. else {\
  405. randomProblem();\
  406. }\
  407. }\
  408. else {\
  409. setTimeout(turntoProblem, 10);\
  410. }\
  411. }';
  412. SearchBox.after(RandomButton);
  413. RandomButton.after(RandomScript);
  414. }
  415. }
  416.  
  417. function DiscussionCard() {
  418. var discrd = document.createElement('div');
  419. discrd.setAttribute('class', 'giscus');
  420. document.getElementsByClassName('uoj-footer')[0].before(discrd);
  421. var script = document.createElement('script');
  422. script.setAttribute('src', 'https://giscus.app/client.js');
  423. script.setAttribute('data-repo', 'Sukwants/Discuss124OJ');
  424. script.setAttribute('data-repo-id', 'R_kgDOImiZLA');
  425. script.setAttribute('data-category', 'Ideas');
  426. script.setAttribute('data-category-id', 'DIC_kwDOImiZLM4CTCIj');
  427. script.setAttribute('data-mapping', 'pathname');
  428. script.setAttribute('data-strict', '0');
  429. script.setAttribute('data-reactions-enabled', '1');
  430. script.setAttribute('data-emit-metadata', '0');
  431. script.setAttribute('data-input-position', 'top');
  432. script.setAttribute('data-theme', 'preferred_color_scheme');
  433. script.setAttribute('data-lang', 'zh-CN');
  434. script.setAttribute('crossorigin', 'anonymous');
  435. script.setAttribute('async', '');
  436. document.getElementsByTagName('body')[0].appendChild(script);
  437. GM_addStyle('\
  438. .giscus {\
  439. display: ' + (Academic == true ? 'none' : 'unset') + ';\
  440. }\
  441. .giscus-frame {\
  442. margin-top: 20px;\
  443. }');
  444. }
  445.  
  446. function CodeBlock() {
  447. const ManageStatementExp = /^.*\/manage\/statement(\?.*){0,1}$/
  448. GM_addStyle('\
  449. @import url(https://cdn.jsdelivr.net/npm/firacode@6.2.0/distr/fira_code.css);\
  450. code {\
  451. font-family: "Fira Code";\
  452. }\
  453. code.sh_cpp>span {\
  454. font-style: normal !important;\
  455. font-weight: 400 !important;\
  456. }\
  457. code.sh_cpp>span.sh_preproc,\
  458. code.sh_cpp>span.sh_keyword,\
  459. code.sh_cpp>span.sh_type {\
  460. color: #8959a8;\
  461. }\
  462. code.sh_cpp>span.sh_string {\
  463. color: #718c00;\
  464. }\
  465. code.sh_cpp>span.sh_cbracket {\
  466. color: #4d4d4c;\
  467. }\
  468. code.sh_cpp>span.sh_symbol {\
  469. color: #3e999f;\
  470. }\
  471. code.sh_cpp>span.sh_number {\
  472. color: #f5871f;\
  473. }\
  474. code.sh_cpp>span.sh_function {\
  475. color: #4271ae;\
  476. }\
  477. code.sh_cpp>span.sh_comment {\
  478. color: #8e908c;\
  479. }\
  480. .copybutton {\
  481. float: right;\
  482. background-color: rgb(0,0,0,.1);\
  483. padding: .25em .625em;\
  484. border: 0 solid transparent;\
  485. border-radius: .28571429rem;\
  486. }\
  487. .copybutton:hover {\
  488. background-color: rgb(0,0,0,.2);\
  489. }\
  490. .copybutton:focus {\
  491. background-color: rgb(0,0,0,.2);\
  492. outline: none;\
  493. }');
  494. if (!ManageStatementExp.test(window.location.href)) {
  495. setTimeout(function(){
  496. var CodeBlocks = document.getElementsByTagName('pre');
  497. for (var cb in CodeBlocks) {
  498. if (CodeBlocks[cb] && CodeBlocks[cb].nodeType) {
  499. var Content = CodeBlocks[cb].textContent;
  500. var InputId = Math.round(Math.random() * 998244353);
  501. var ButtonId = Math.round(Math.random() * 998244353);
  502. CodeBlocks[cb].innerHTML = '<button class="copybutton" id = "' + ButtonId + '" onclick="\
  503. var ib = document.getElementById(\'' + InputId + '\');\
  504. ib.setAttribute(\'style\', \'display:initial\');\
  505. ib.value = \'' + Content.replace(/\\/g, '\\\\').replace(/\n/g, '\\n').replace(/'/g, '\\&#39;').replace(/"/g, '&#34;') + '\';\
  506. ib.select();\
  507. document.execCommand(\'copy\');\
  508. ib.setAttribute(\'style\', \'display:none\');\
  509. var ic = document.getElementById(\'' + ButtonId + '\');\
  510. ic.innerHTML = \'已复制\';\
  511. setTimeout(function() { ic.innerHTML = \'复制\'; }, 500);">复制</button>' + CodeBlocks[cb].innerHTML;
  512. var InputBox = document.createElement('textarea');
  513. InputBox.setAttribute('id', InputId);
  514. InputBox.setAttribute('style', 'display:none');
  515. CodeBlocks[cb].appendChild(InputBox);
  516. }
  517. }
  518.  
  519. }, 30);
  520. }
  521. }
  522.  
  523. function TableStyle() {
  524. var Tables = document.getElementsByTagName('table');
  525. for (var table in Tables) {
  526. if (Tables[table].nodeType && Tables[table].parentNode.getAttribute('class') != 'legend' && !Tables[table].classList.length) {
  527. Tables[table].classList.add('table', 'table-bordered');
  528. }
  529. }
  530. var ths = document.getElementsByTagName('th');
  531. for (var th in ths) {
  532. if (ths[th].nodeType && ths[th].getAttribute('align')) {
  533. ths[th].setAttribute('style', 'text-align:' + ths[th].getAttribute('align'));
  534. }
  535. }
  536. }
  537.  
  538. function SubmissionCard() {
  539. setTimeout(function() {
  540. var Content = document.getElementsByClassName('uoj-content')[0];
  541. if (Content.childElementCount == 3) {
  542. var Table = Content.children[0];
  543. var TabList = document.createElement('ul');
  544. TabList.setAttribute('class', 'nav nav-tabs');
  545. TabList.setAttribute('role', 'tablist');
  546. TabList.innerHTML = '<li class="nav-item"><a class="nav-link active" href="#test-cases" role="tab" data-toggle="tab" aria-selected="true"><span class="glyphicon glyphicon-check"></span> 测试点信息</a></li><li class="nav-item"><a class="nav-link" href="#source" role="tab" data-toggle="tab" aria-selected="false"><span class="glyphicon glyphicon-file"></span> 源代码</a></li>';
  547. var TabContent = document.createElement('div');
  548. TabContent.setAttribute('class', 'tab-content');
  549. TabContent.innerHTML = '<div class="tab-pane card active" id="test-cases"><div class="card-body">' + Content.children[2].children[1].innerHTML + '</div></div><div class="tab-pane card" id="source"><div class="card-body">' + Content.children[1].children[1].innerHTML + '</div></div>';
  550. Content.innerHTML = "";
  551. Content.appendChild(Table);
  552. Content.appendChild(TabList);
  553. Content.appendChild(TabContent);
  554. }
  555. }, 50);
  556. }
  557.  
  558. function downloadData() {
  559. var DownloadTag = document.createElement('a');
  560. DownloadTag.setAttribute('role', 'button');
  561. DownloadTag.setAttribute('class', 'btn btn-primary float-right');
  562. DownloadTag.setAttribute('href', '/download.php?type=problem&id=' + window.location.href.match(ProblemRegExp)[1]);
  563. DownloadTag.setAttribute('target', '_blank');
  564. DownloadTag.innerHTML = '<span class="glyphicon glyphicon-download-alt"></span> 下载数据';
  565. document.getElementsByClassName("btn btn-info float-right")[0].after(DownloadTag);
  566. }
  567.  
  568. function changeGravatarURL() {
  569. const GravatarURLRegExp = /\/\/cn.gravatar.com\/avatar\/(.*)$/;
  570. var Gravatar = document.getElementsByClassName('img-thumbnail')[0];
  571. if (Gravatar && Gravatar.nodeType){
  572. console.log(Gravatar);
  573. Gravatar.setAttribute('src', '//gravatar.loli.net/avatar/' + Gravatar.getAttribute('src').match(GravatarURLRegExp)[1]);
  574. }
  575. var Gravatars = document.getElementsByClassName('img-rounded');
  576. for (var gravatar in Gravatars) {
  577. if (Gravatars[gravatar] && Gravatars[gravatar].nodeType && GravatarURLRegExp.test(Gravatars[gravatar].getAttribute('src'))) {
  578. Gravatars[gravatar].setAttribute('src', '//gravatar.loli.net/avatar/' + Gravatars[gravatar].getAttribute('src').match(GravatarURLRegExp)[1]);
  579. }
  580. }
  581. }
  582.  
  583. function clearNameStyle() {
  584. const NameExp = /^(.{1,}?)( .*)*$/;
  585. var Names = document.getElementsByClassName('uoj-username');
  586. for (var i in Names) {
  587. if (!Names[i].innerHTML) continue;
  588. Names[i].innerHTML = Names[i].textContent.match(NameExp)[1];
  589. }
  590. var Honors = document.getElementsByClassName('uoj-honor');
  591. for (var j in Honors) {
  592. if (!Honors[j].innerHTML) continue;
  593. Honors[j].innerHTML = Honors[j].textContent.match(NameExp)[1];
  594. }
  595. }
  596.  
  597. function NameColor() {
  598. var Names = document.getElementsByClassName('uoj-username');
  599. var NeedsRepeat = false;
  600. for (var i in Names) {
  601. if (Names[i].innerHTML && NameColorList[Names[i].innerHTML]) {
  602. Names[i].style = 'color:' + NameColorList[Names[i].innerHTML][0];
  603. var resN = '';
  604. for (var charN = 1; charN < NameColorList[Names[i].innerHTML].length; ++charN) {
  605. resN = resN + '<font style="color:' + NameColorList[Names[i].innerHTML][charN] + '">' + Names[i].innerHTML.substring(charN - 1, charN) + '</font>';
  606. }
  607. Names[i].innerHTML = resN + Names[i].innerHTML.substring(NameColorList[Names[i].innerHTML].length - 1);
  608. if (Names[i].parentElement.getAttribute('class') == 'legendLabel') {
  609. NeedsRepeat = true;
  610. }
  611. }
  612. }
  613. if (NeedsRepeat) {
  614. setInterval(function(){
  615. var Names = document.getElementsByClassName('uoj-username');
  616. for (var i in Names) {
  617. if (Names[i].innerHTML && Names[i].parentElement.getAttribute('class') == 'legendLabel' && NameColorList[Names[i].innerHTML]) {
  618. Names[i].style = 'color:' + NameColorList[Names[i].innerHTML][0];
  619. var resN = '';
  620. for (var charN = 1; charN < NameColorList[Names[i].innerHTML].length; ++charN) {
  621. resN = resN + '<font style="color:' + NameColorList[Names[i].innerHTML][charN] + '">' + Names[i].innerHTML.substring(charN - 1, charN) + '</font>';
  622. }
  623. Names[i].innerHTML = resN + Names[i].innerHTML.substring(NameColorList[Names[i].innerHTML].length - 1);
  624. }
  625. }
  626. }, 200);
  627. }
  628. var Honors = document.getElementsByClassName('uoj-honor');
  629. for (var j in Honors) {
  630. if (Honors[j].innerHTML && NameColorList[Honors[j].innerHTML]) {
  631. Honors[j].style = 'color:' + NameColorList[Honors[j].innerHTML][0];
  632. var resH = '';
  633. for (var charH = 1; charH < NameColorList[Honors[j].innerHTML].length; ++charH) {
  634. resH = resH + '<font style="color:' + NameColorList[Honors[j].innerHTML][charH] + '">' + Honors[j].innerHTML.substring(charH - 1, charH) + '</font>';
  635. }
  636. Honors[j].innerHTML = resH + Honors[j].innerHTML.substring(NameColorList[Honors[j].innerHTML].length - 1);
  637. }
  638. }
  639. }
  640.  
  641. function NameBadge() {
  642. var Names = document.getElementsByClassName('uoj-username');
  643. for (var i in Names) {
  644. if (!Names[i].innerHTML) continue;
  645. var name = Names[i].textContent;
  646. if (CCFBadgeList[name] && Names[i].parentElement.getAttribute('class') != 'legendLabel') {
  647. Names[i].innerHTML = Names[i].innerHTML + ' <svg width="1em" height="1em" data-v-303bbf52="" aria-hidden="true" focusable="false" data-prefix="fad" data-icon="badge-check" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="margin-bottom:.25em!important;bottom:10px;--fa-primary-color:#fff;--fa-secondary-color:' + CCFBadgeList[name] + ';--fa-secondary-opacity:1;"><g data-v-303bbf52="" class="fa-group"><path data-v-303bbf52="" fill="var(--fa-secondary-color)" d="M512 256a88 88 0 0 0-57.1-82.4A88 88 0 0 0 338.4 57.1a88 88 0 0 0-164.8 0A88 88 0 0 0 57.1 173.6a88 88 0 0 0 0 164.8 88 88 0 0 0 116.5 116.5 88 88 0 0 0 164.8 0 88 88 0 0 0 116.5-116.5A88 88 0 0 0 512 256zm-144.8-44.25l-131 130a11 11 0 0 1-15.55-.06l-75.72-76.33a11 11 0 0 1 .06-15.56L171 224a11 11 0 0 1 15.56.06l42.15 42.49 97.2-96.42a11 11 0 0 1 15.55.06l25.82 26a11 11 0 0 1-.08 15.56z" class="fa-secondary"></path></g></svg>';
  648. }
  649. if (TagBadgeList[name] && Names[i].parentElement.getAttribute('class') != 'legendLabel') {
  650. Names[i].innerHTML = Names[i].innerHTML + ' <span style="background-color:' + TagBadgeList[name][0] + ';padding:0.2em 0.6em;border-radius:.2em;color:#fff;font-size:0.7em;font-weight:bold;display:inline-block">' + TagBadgeList[name][1] + '</span>';
  651. }
  652. }
  653. var Honors = document.getElementsByClassName('uoj-honor');
  654. for (var j in Honors) {
  655. if (!Honors[j].innerHTML) continue;
  656. var honor = Honors[j].textContent;
  657. if (CCFBadgeList[honor]) {
  658. Honors[j].innerHTML = Honors[j].innerHTML + ' <svg width="1em" height="1em" data-v-303bbf52="" aria-hidden="true" focusable="false" data-prefix="fad" data-icon="badge-check" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="margin-bottom:.25em!important;bottom:10px;--fa-primary-color:#fff;--fa-secondary-color:' + CCFBadgeList[honor] + ';--fa-secondary-opacity:1;"><g data-v-303bbf52="" class="fa-group"><path data-v-303bbf52="" fill="var(--fa-secondary-color)" d="M512 256a88 88 0 0 0-57.1-82.4A88 88 0 0 0 338.4 57.1a88 88 0 0 0-164.8 0A88 88 0 0 0 57.1 173.6a88 88 0 0 0 0 164.8 88 88 0 0 0 116.5 116.5 88 88 0 0 0 164.8 0 88 88 0 0 0 116.5-116.5A88 88 0 0 0 512 256zm-144.8-44.25l-131 130a11 11 0 0 1-15.55-.06l-75.72-76.33a11 11 0 0 1 .06-15.56L171 224a11 11 0 0 1 15.56.06l42.15 42.49 97.2-96.42a11 11 0 0 1 15.55.06l25.82 26a11 11 0 0 1-.08 15.56z" class="fa-secondary"></path></g></svg>';
  659. }
  660. if (TagBadgeList[honor]) {
  661. Honors[j].innerHTML = Honors[j].innerHTML + ' <span style="background-color:' + TagBadgeList[honor][0] + ';padding:0.2em 0.6em;border-radius:.2em;color:#fff;font-size:0.7em;font-weight:bold;display:inline-block">' + TagBadgeList[honor][1] + '</span>';
  662. }
  663. }
  664. }