Hfoj Better by cosf

Changelogs

v1.0.0

  • Added exrand.

v1.1.0

  • Removed some unnecessary objects.
  • Optimized exrand.

v1.2.1

  • Added code submission block in problem pages.

v1.3.1

  • Added submission viewer block in problem pages.

v1.4.1

  • Optimized yiyan.
  • Added more yiyan.
  • Optimized exrand.
  • Updated submission viewer.
  • Added hide feature to sections.

v1.5.0

  • Added cph support.
  • Added cf domain submission support.

v1.6.0

  • Updated submission status code.
  • Changed mods' showing condition.
  • Added jumping function (fast jumping between domains).

v1.7.0

  • Added April Fools' Day's Effect. This effect will be turned on from April 1st to 3rd.
  • Updated jumping function in record page.
  • Updated submission viewer.
  • Added blog icon in user page.

v1.8.0

  • Added Hfoj Badge.
  • Updated blog icon.

Source

// ==UserScript==
// @name         Hfoj Better
// @namespace    http://hfoj.net/
// @version      1.8.0
// @description  Add functions to hfoj
// @author       cosf
// @match        http://hfoj.net/*
// @match        http://hfoj.net
// @match        10.80.74.11/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @connect      localhost:27121/
// @icon         http://hfoj.net/favicon.ico
// ==/UserScript==

!function(){"use strict";const e=location.pathname,t=e.match(/\/d\/(\w+)/)?.[1],n=t?e.replace(/\/d\/(\w+)/,""):e,o=function(e){let t={};return e.substring(1).split("&").forEach((e=>{let n=e.split("=");t[n[0]]=n[1]})),t}(location.search);!function(e){let t={};e.split("; ").forEach((e=>{let n=e.split("=");t[n[0]]=n[1]}))}(document.cookie);function a(e){return o[e]?`${e}=${o[e]}`:""}const s=$("a.nav__item").last()[0].href.match(/\d+$/)[0];function i(){return t?`/d/${t}`:""}const c=["SGFwcHlib2IgU2F5cyBZb3hp","SGFwcHlib2Igc2F5cyAiQ3VhenlveGkgeW94aSEi","RG9uJ3QgYmUgZGVjYWRlbnQhIQ==","JUU3JThFJUE5TyVFNyU4RSVBOSVFNyU5QSU4NA==","JUU2JThCJTlDJUU4JUIwJUEyJUU2JTlDJTg4JUU0JUJBJUFF","JUU2JUIwJUE3JUU0JUJDJTlBJUU3JTg3JTgzJUVGJUJDJThDJUU2JUIwJUE3JUU2JTk3JUJBJUU3JTg3JTgz","JUU2JTlDJTg4JUU0JUJBJUFFJUU1JUE1JUJEJUU5JTk3JUFBJUVGJUJDJThDJUU2JThCJTlDJUU4JUIwJUEyJUU2JTlDJTg4JUU0JUJBJUFF","JUU4JThCJUE1JUU4JUEyJUFCJUU1JThGJTkxJUU3JThFJUIwJUU4JUJGJTlEJUU4JUE3JTg0JUVGJUJDJThDJUU1JUIwJTg2JUU4JUEyJUFCJTIwQ0NGJTIwJUU3JUE2JTgxJUU4JUI1JTlCJUU0JUI4JTg5JUU1JUI5JUI0JUUzJTgwJTgy","WW91J3JlJTIwd3JvbmcuJTIwSGVyZSUyMGlzJTIwd2h5Lg==","SGFwcHklMjBCb2IlMjBoZWxwcyUyMHlvdSUyMHRvJTIwZmVlbCUyMGxpa2UlMjBhJTIwcGVyc29uJTJDJTIwbm90JTIwYSUyMHBhdGllbnQu"],d=["其他 (0)","入门 (1)","普及- (2)","普及/提高- (3)","普及+/提高 (4)","提高+/省选- (5)","省选/NOI- (6)","NOI/NOI+/CTSC (7)","(8)","(9)","(10)"];localStorage.getItem("selectedDifficulties")||localStorage.setItem("selectedDifficulties","[1,1,1,1,1,1,1,1]");const r=JSON.parse(localStorage.getItem("selectedDifficulties")),l=["unselected","selected"],p={0:"Waiting",1:"Accepted",2:"Wrong Answer",7:"Compile Error",8:"System Error",20:"Running",21:"Compiling",22:"Fetched"},u={0:"schedule",1:"check",2:"close",7:"close",8:"close",20:"hourglass",21:"hourglass",22:"hourglass"},h={0:"#000000",1:"#61c25a",2:"#fb6666",7:"#fb6666",8:"#fb6666",20:"#f3a83f",21:"#f3a83f",22:"#f3a83f"},m={0:"#000000",1:"#25ad40",2:"#fb5555",7:"#fb5555",8:"#fb5555",20:"#f3a83f",21:"#f3a83f",22:"#f3a83f"},b={0:"#000000",1:"#90ffa0",2:"#ffbbbb",7:"#ffbbbb",8:"#ffbbbb",20:"#fff8bf",21:"#fff8bf",22:"#fff8bf"},g={home:/^\/$/,problems:/^\/p(\/?)$/,problem:/^\/p\/\w+(\/?)$/,pid:/([^\/]+)(\/?)$/,homeworkIn:/^\/homework\/(\w+)/,discuss:/^\/discuss(\/?)$/,discussIn:/^\/discuss\/(\w+)/,record:/^\/record(\/?)$/,recordIn:/^\/record\/(\w+)/,contestIn:/^\/contest\/(\w+)/,user:/^\/user\/(\d+)/,userIn:/^\/user\/(\w+)/,fileUser:/^\/file\/(\d+)/};function f(e,t){let n=!1;return t.forEach((t=>n=n||e.match(g[t]))),n}const J=["luogu","system","python","ybtqm","ybttg","jjzn","codeforces"],v={luogu:"luogu.cxx/14/gcco2",[null]:"cc.cc17o2",[void 0]:"cc.cc17o2",system:"cc.cc17o2",python:"py.py3",ybtqm:"cc.cc17o2",ybttg:"cc.cc17o2",jjzn:"cc.cc17o2",codeforces:"codeforces.54"},_={luogu:"NOI 标准语言 C++14 (O2)",[null]:"C++17 (O2)",[void 0]:"C++17 (O2)",system:"C++17 (O2)",python:"Python 3",ybtqm:"C++17 (O2)",ybttg:"C++17 (O2)",jjzn:"C++17 (O2)",codeforces:"GNU G++17 7.3.0"},U={luogu:"洛谷",[null]:"主站",[void 0]:"主站",system:"主站",python:"Py",ybtqm:"启蒙",ybttg:"提高",jjzn:"进阶",codeforces:"CF"};if($('<style>\n.section {\nborder-radius: 10px;\n}\n\n.exrand-block {\nwidth: 20px;\nheight: 20px;\nmargin: 10px;\nborder: 1px solid black;\ndisplay: block;\ntext-align: center;\nline-height: 20px;\n}\n\n.exrand-select {\n/* border: 1px solid black; */\n}\n\n.exrand-selector {\ndisplay: flex;\n}\n\n.exrand-submit {\nmargin-top: 10px;\n}\n\n.exrand-text {\nmargin-top: 10px;\nmargin-bottom: 10px;\nline-height: 20px;\n}\n\n.jmp-right {\nmargin-right: 10px !important;\n}\n\n.sb-margin-left {\nmargin-left: 8px;\n}\n\n.sb-warning {\nbackground-color: #e78 !important;\n}\n\n.smc-icon {\nfont-family: vj4icon;\n}\n\n.smc-pass::before {\ncontent: "\\ea0a";\n}\n\n.smc-wait::before {\ncontent: "\\ea2d";\n}\n\n.smc-incr::before {\ncontent: "\\ea0e";\n}\n\n.smc-sbm {\ndisplay: flex;\nflex-direction: row;\nheight: 40.15px;\n}\n\n.smc-sbmi {\nheight: 40.15px;\nline-height: 40.15px;\n}\n\n.smc-sbms {\npadding-left: 10px;\n}\n\n*[unselected] {\nbackground-color: var(--exrand-unselected);\n}\n\n*[selected] {\nbackground-color: var(--exrand-selected);\n}\n\n* {\n--exrand-selected: rgb(20 255 20);\n--exrand-unselected: rgb(128 128 128);\n--exrand-background: rgb(238 238 238);\n}\n</style>').appendTo($(document.body)),f(n,["home"])&&($('.section.side:contains("推荐")').remove(),$('.section.side:contains("一言")').remove()),f(n,["problems"])&&$('.section.side:contains("进入编辑模式")').remove(),f(n,["discuss"])&&$('.section.side:contains("讨论节点")').remove(),$(".error__container").length>0){let y=$("h1").first();y.text("错误!3秒后返回上一页");let x=setTimeout((()=>{history.go(-1)}),3e3);y.on("dblclick",(()=>{y.text("错误!"),clearTimeout(x)}))}else{if(f(n,["home"])){$(`<div class="section side" style="border-radius: 10px;">\n<div class="section__header">\n<h1 class="section__title">\n一言\n</h1>\n</div>\n<div class="section__body">\n<p id="yiyan">\n${decodeURIComponent(atob(c[Math.floor(Math.random()*c.length)]))}\n</p>\n</div>\n</div>`).prependTo($(".large-3, .medium-3").first())}if(f(n,["userIn"])){let T=n.match(g.user)[1],w=$('*:contains("♂")').length,k=$('*:contains("♀")').length;$(`<a class="profile-header__contact-item tooltip drop-target drop-abutted drop-abutted-top drop-element-attached-bottom drop-element-attached-center drop-target-attached-top drop-target-attached-center" href="${i()}/blog/${T}" target="_blank" data-tooltip="查看${w?"他":k?"她":"Ta"}的博客">\n<span class="icon icon-book"></span>\n</a>`).prependTo(".profile-header__contact-bar")}{let I=JSON.parse(GM_getValue("hb-badge",JSON.stringify({34:{content:"Happybob",color:"#575757",textColor:"white"},35:{content:"cosf | 月亮",color:"#575757",textColor:"white"}})));setTimeout((()=>{if($(".user-profile-link").each((function(){let e=$(this),t=e.children("a").first();if(!t.length)return;let n=t.attr("href").match(g.user)[1];if(I[n]){$(`<a class="user-profile-badge v-center tooltip drop-target drop-abutted drop-abutted-top drop-element-attached-bottom drop-element-attached-center drop-target-attached-top drop-target-attached-center sb-margin-left" href="${i()}/user/${n}" data-tooltip="Hfoj Better Badge"\nstyle="color:${I[n].textColor};background-color:${I[n].color}">\n${I[n].content}\n</a>`).insertAfter(e.children()[1])}})),$("*[data-uid]").each((function(){let e=$(this),t=e.attr("data-uid");if(I[t]){$(`<a class="user-profile-badge v-center tooltip drop-target drop-abutted drop-abutted-top drop-element-attached-bottom drop-element-attached-center drop-target-attached-top drop-target-attached-center sb-margin-left" href="${i()}/user/${t}" data-tooltip="Hfoj Better Badge"\nstyle="color:${I[t].textColor};background-color:${I[t].color}">\n${I[t].content}\n</a>`).insertAfter(e.children().first().children().first().children()[1])}})),f(n,["userIn"])){let e=n.match(g.user)[1];if(I[e]){$(`<a class="user-profile-badge v-center tooltip drop-target drop-abutted drop-abutted-top drop-element-attached-bottom drop-element-attached-center drop-target-attached-top drop-target-attached-center sb-margin-left" href="${i()}/user/${e}" data-tooltip="Hfoj Better Badge"\nstyle="color:${I[e].textColor};background-color:${I[e].color}">\n${I[e].content}\n</a>`).appendTo($(".profile-header__main").children().first())}}}),2e3);$('<li class="nav__list-item dropdown nav__dropdown drop-target drop-element-attached-top drop-element-attached-right drop-target-attached-bottom drop-target-attached-right"\ndata-dropdown-custom-class="nav__dropdown"\ndata-dropdown-target="#menu-nav-badge"\ndata-dropdown-disabledconstraintowindow\ndata-dropdown-trigger-desktop-only>\n<span class="nav__item">\n<span class="icon icon-edit"></span>\n设置 Badge\n</span>\n</li>').prependTo($(".nav__list--secondary"));new MutationObserver((function(e){for(let t of e)if("childList"==t.type){let e=$(t.addedNodes[0]).children('*:contains("undefined")');if(!e.length)return;e.text("");let n=$('<ol id="#menu-nav-badge" class="dropdown-target menu">\n<li class="menu__item">\n<div class="menu__link">\n<span class="icon icon-account--circle"></span>\n用户 uid\n</div>\n</li>\n</ol>').appendTo(e),o=$('<input class="expanded"/>').appendTo($('<div class="menu__link"></div>').appendTo($('<li class="menu__item"></li>').appendTo(n)));n.append('<li class="menu__seperator"></li>','<li class="menu__item">\n<div class="menu__link">\n<span class="icon icon-comment--text"></span>\nBadge\n</div>\n</li>');let a=$('<input class="expanded"/>').appendTo($('<div class="menu__link"></div>').appendTo($('<li class="menu__item"></li>').appendTo(n)));n.append('<li class="menu__seperator"></li>','<li class="menu__item">\n<div class="menu__link">\n<span class="icon icon-erase"></span>\nBackground Color\n</div>\n</li>');let s=$('<input class="expanded" value="#575757"/>').appendTo($('<div class="menu__link"></div>').appendTo($('<li class="menu__item"></li>').appendTo(n)));n.append('<li class="menu__seperator"></li>','<li class="menu__item">\n<div class="menu__link">\n<span class="icon icon-erase"></span>\nText Color\n</div>\n</li>');let i=$('<input class="expanded" value="white"/>').appendTo($('<div class="menu__link"></div>').appendTo($('<li class="menu__item"></li>').appendTo(n)));n.append('<li class="menu__seperator"></li>');let c=$('<div class="button expanded">设置</div>').appendTo($('<div class="menu__link"></div>').appendTo($('<li class="menu__item"></li>').appendTo(n))),d=$('<div class="button expanded sb-warning">清除数据</div>').appendTo($('<div class="menu__link"></div>').appendTo($('<li class="menu__item"></li>').appendTo(n)));c.on("click",(()=>{I[o.val()]={content:a.val(),color:s.val(),textColor:i.val()},GM_setValue("hb-badge",JSON.stringify(I))})),d.on("click",(()=>{let e=prompt("你确定要清除数据吗?\n- 输入 1 清除指定对象的 Badge;\n- 输入 2 清除所有人的 Badge(除了默认项);\n- 输入其他任何东西取消。");"1"==e&&(I[o.val()]=void 0,GM_setValue("hb-badge",JSON.stringify(I))),"2"==e&&(I={34:{content:"Happybob",color:"#575757",textColor:"white"},35:{content:"cosf | 月亮",color:"#575757",textColor:"white"}},GM_setValue("hb-badge",JSON.stringify(I)))}))}})).observe(document.body,{childList:!0})}{let j,C;f(n,["record"])?($('.section:contains("由语言")').append($('<div class="section__header">\n<h1 class="section__title">\n跳转\n</h1>\n</div>')),j=$('<div class="section__body"></div>').appendTo($('.section:contains("由语言")')),C=$("<div></div>").appendTo(j)):(j=$('<div class="section side" type="border-radius: 10px;">\n<div class="section__header">\n<h1 class="section__title">\n跳转\n</h1>\n</div>\n</div>').appendTo($("*[data-sticky], .large-3, .medium-3").first()),C=$('<div class="section__body"></div>').appendTo(j)),J.forEach((e=>{let t=$(`<div class="button jmp-right">${U[e]}</div>`);t.on("click",(()=>{f(n,["problem","homeworkIn","recordIn","discussIn","contestIn"])?location=`/d/${e}/`:location=`/d/${e}${n}${location.search}`})),t.appendTo(C)}))}if(f(n,["home","problems","problem"])){let S=$('<div class="section side" style="border-radius: 10px;">\n<div class="section__header">\n<h1 class="section__title">\n随机 ex\n</h1>\n</div>\n</div>'),B=$('<div class="section__body">\n</div>').appendTo(S);if(e.match(/\/p\/\w+/)){let M=$("*:contains(难度).problem__tag-item");M.text(M.text().replace(/\d+/,(e=>d[e])))}let G=$('<div class="exrand-select">\n<div class="expanded button">\n选择难度\n</div>\n</div>');class E{constructor(e,t){this.jqe=$(`<div exrand-difficulty-${e} class="exrand-selector">\n<span class="exrand-text">${d[e]}</span>\n</div>`).appendTo(t),this.box=$(`<span class="exrand-block" ${l[r[e]]}></span>`).prependTo(this.jqe),this.jqe.on("click",(()=>{this.box.removeAttr(l[r[e]]),r[e]=1-r[e],localStorage.setItem("selectedDifficulties",JSON.stringify(r)),this.box.attr(l[r[e]],"")}))}}for(let O=0;O<8;O++)new E(O,G);G=G.appendTo(B);let F=!1;G.children().first().on("click",(()=>{F?G.find(".exrand-selector").hide():G.find(".exrand-selector").show(),F=!F})),G.find(".exrand-selector").hide(),$('<div>\n<p class="expanded button exrand-submit">\n随机\n</p>\n</div>').appendTo(B).on("click",(()=>{let e="";r.forEach(((t,n)=>{t&&(e+=","+n)})),e=e.substring(1),$.ajax({method:"GET",url:`${i()}/p?q=difficulty:${e}`,headers:{accept:"application/json"},success(t){let n=t.pcount,o=Math.ceil(Math.random()*n),a=Math.ceil(o/100),s=(o-1)%100;$.ajax({method:"GET",url:`${i()}/p?q=difficulty:${e}&page=${a}`,headers:{accept:"application/json"},success(e){console.log(e);let t=e.pdocs[s].docId;location=`${i()}/p/${t}`}})}})})),S=S.prependTo($(".large-3, .medium-3").first())}if(f(n,["problem"])){let D=n.match(g.pid)[1],N=$('<div class="section__body"></div>');class q{constructor(e,t){this.subid=e,console.log(this.subid),this.jqe=$(`<a class="smc-sbm" href="${i()}/record/${this.subid}" target="_blank"></a>`)[t](N),this.update()}update(){let e=this;$.ajax({url:`${i()}/record/${e.subid}?${a("tid")}`,method:"GET",headers:{accept:"application/json"},success(t){let n=t.rdoc;console.log(n.status),(n.status>8||0==n.status)&&setTimeout(e.update.bind(e),500),n.judgeAt||(n.judgeAt="Judging"),e.jqe.html(`<span style="border-left: .1875rem solid ${h[n.status]}; color: ${m[n.status]}" class="smc-sbmi smc-sbms">\n<span class="icon icon-${u[n.status]}"></span>\n${n.score} ${p[n.status]}\n</span>\n<span style="margin-left: auto">\n${n.judgeAt}\n</span>\n`),n.progress||(n.progress=0),e.jqe.css(`background", "rgb(0, 0) linear-gradient(to right, ${b[n.status]} ${n.progress}%, rgba(0, 0, 0, 0) ${n.progress}%) repeat scroll 0% 0% / auto border-box border-box`)}})}}function H(){$.ajax({url:`${i()}/record?uidOrName=${s}&pid=${D}&${a("tid")}`,method:"GET",headers:{accept:"application/json"},success(e){e.rdocs.forEach((e=>{new q(e._id,"appendTo")}))}})}function V(e){let t=e.url.match(g.pid)[0];new q(t,"prependTo")}H();let A=$('<input type="submit" class="rounded primary button" value="递交"></input>');A.on("click",(()=>{let e=$("textarea").val();fetch(`${i()}/p/${D}/submit?${a("tid")}`,{headers:{accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","accept-language":"zh-CN,zh;q=0.9,en;q=0.8","cache-control":"max-age=0","content-type":"multipart/form-data; boundary=----WebKitFormBoundaryHappybobSaysYoxi","upgrade-insecure-requests":"1"},referrer:`${i()}/p/${D}/submit`,referrerPolicy:"strict-origin-when-cross-origin",body:`------WebKitFormBoundaryHappybobSaysYoxi\r\nContent-Disposition: form-data; name="lang"\r\n\r\n${v[t]}\r\n------WebKitFormBoundaryHappybobSaysYoxi\r\nContent-Disposition: form-data; name="code"\r\n\r\n${e}\r\n------WebKitFormBoundaryHappybobSaysYoxi\r\nContent-Disposition: form-data; name="file"; filename=""\r\nContent-Type: application/octet-stream\r\n\r\n\r\n------WebKitFormBoundaryHappybobSaysYoxi--\r\n`,method:"POST",mode:"cors",credentials:"include"}).then(V)}));let W=$(`<div class="section__body">\n<label>\n代码语言:${_[t]}\n</label>\n<div class="medium-12">\n<textarea class="textbox monospace" spellcheck="false"></textarea>\n</div>\n</div>`).append(A),z=$('<div class="section">\n<div class="section__header">\n提交代码\n</div>\n</div>').append(W),Y=$('<div class="section">\n<div class="section__header">\n提交记录\n</div>\n</div>').append(N);$(".medium-9.columns").append(z,Y)}if($(".section").each((function(){if(2!=$(this).children().length)return;let e=$(this).children(".section__body");if(1!=e.length)return;let t=$(this).children(".section__header");if(1!=t.length)return;let n=$('<div class="button">隐藏</div>').appendTo(t);n.on("click",(()=>{"隐藏"==n.text()?(e.hide(),n.text("显示")):(e.show(),n.text("隐藏"))}))})),f(n,["problem"])){let Q=n.match(g.pid)[1],R=$('<div class="section side" style="border-radius: 10px;">\n<div class="section__header">\n<h1 class="section__title">\n传送至 cph\n</h1>\n</div>\n</div>'),K=$('<div class="expanded button">传送</div>');K.on("click",(()=>{let e=[],t=1;for(;1==$(`code.language-input${t}`).length;)e.push({input:$(`code.language-input${t}`).text(),output:$(`code.language-output${t}`).text()}),t++;GM_xmlhttpRequest({url:"http://localhost:27121/",method:"POST",data:JSON.stringify({batch:{id:"hfoj-better",size:1},name:Q,url:location.toString(),interactive:"false",memoryLimit:524288,timeLimit:5e3,tests:e,input:{type:"stdin"},output:{type:"stdout"},testType:"single"}),onload(e){502==e.status&&alert("未启动 cph")},onerror(){alert("传送失败")}})})),R.append($('<div class="section__body"></div>').append(K)).prependTo($(".large-3, .medium-3").first())}if((new Date).toDateString().match(/Apr 0[1-3]/)){function L(){$("*").each((function(){this.style.color=`rgb(${Math.floor(256*Math.random())} ${Math.floor(256*Math.random())} ${Math.floor(256*Math.random())})`})),setTimeout(L,1e3)}$("#yiyan").text("Happy April Fools' Day!"),L()}}}();