// ==UserScript==
// @name EXGF
// @namespace http://tampermonkey.net/
// @version 1.6
// @description /oh /hsh /zhq
// @author ExplodingKonjac && JWRuixi
// @license GPLv3
// @match http://*.gdfzoj.com/*
// @icon http://www.gdfzoj.com:23380/images/favicon.ico
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
(function () {
"user strict";
var css = "";
css += [
".card table, .tab-content table {",
" background: none;",
"}",
".card, .table {",
" background: rgba(252, 252, 252, .85);",
" border-radius: 5px;",
"}",
"html > body {",
" background-image: url(https://cdn-fusion.imgcdn.store/i/2024/p8HeWzxkl75PEHUJ.png);",
" background-repeat: no-repeat;",
" background-size: cover;",
" background-position: center;",
" background-attachment: fixed;",
"}",
".nav-tabs .nav-link, .nav-pills .nav-link {",
" background-color: #e0f7ff;",
" border-radius: 0px;",
"}",
".nav, .table, .table th, .table td, .card {",
" border: none;",
"}",
".nav-tabs .nav-item.show .nav-link, .nav-tabs .nav-link.active, .nav-pills .nav-link.active, .nav-pills .show>.nav-link {",
" color: #fff;",
" background-color: #3498db;",
" border: none;",
"}",
".row {",
" margin-bottom: 10px;",
"}",
"code {",
" font-family: Fira Code !important;",
"}",
".sh_keyword, .sh_function {",
" font-weight: 600 !important;",
"}",
"h1:is(.text-center), h2:is(.text-center) {",
" color: #fff !important;",
"}"
].join("\n");
if ((new RegExp("http://www.gdfzoj.com:23380/problem/[0-9]+/manage/*").test(document.location.href)) || (new RegExp("http://www.gdfzoj.com:23380/admin/*").test(document.location.href))) {
css += [
"h1, h2, h3, h5, h6, label, .top-buffer-md, p, li, dd, dt {",
" color: #fff !important;",
"}"
].join("\n");
}
if ((new RegExp("http://www.gdfzoj.com:23380/problem/[0-9]+/manage/*").test(document.location.href)) || ((new RegExp("http://www.gdfzoj.com:23380/admin/*").test(document.location.href)) && !(new RegExp("http://www.gdfzoj.com:23380/admin/custom-test").test(document.location.href)))) {
css += [
"h4 {",
" color: #fff !important;",
"}"
].join("\n");
}
if (new RegExp("http://www.gdfzoj.com:23380/problems/*").test(document.location.href)) {
css += [
".row:not(:has(.offset-md-3)) {",
" background: rgba(252, 252, 252, .85);",
" border-radius: 5px;",
" margin-left: 0px;",
" margin-right: 0px;",
"}",
".col-lg-4 {",
" padding-top: 10px;",
" padding-bottom: 8px;",
"}",
".offset-md-3.col-md-6 > .justify-content-center {",
" display: none;",
"}"
].join("\n");
}
if ((new RegExp("http://www.gdfzoj.com:23380/problem/*").test(document.location.href)) || (new RegExp("http://www.gdfzoj.com:23380/contest/[0-9]+/problem/*").test(document.location.href))) {
css += [
".row {",
" margin-left: 0px;",
" margin-right: 0px;",
"}",
".tab-content {",
" background: rgba(252, 252, 252, .85);",
" border-radius: 5px;",
" margin-top: 15px;",
" padding: 15px;",
"}",
".page-header {",
" border-bottom: none !important;",
"}"
].join("\n");
}
if (new RegExp("http://www.gdfzoj.com:23380/submission/*").test(document.location.href)) {
css += [
".card-header.bg-info {",
" background-color: #eee !important;",
"}"
].join('\n');
}
if (typeof GM_addStyle != "undefined") {
GM_addStyle(css);
} else if (typeof PRO_addStyle != "undefined") {
PRO_addStyle(css);
} else if (typeof addStyle != "undefined") {
addStyle(css);
} else {
var node = document.createElement("style");
node.type = "text/css";
node.appendChild(document.createTextNode(css));
var heads = document.getElementsByTagName("head");
if (heads.length > 0) {
heads[0].appendChild(node);
} else {
// no head yet, stick it whereever
document.documentElement.appendChild(node);
}
}
// Select all elements with the class 'uoj-username'
const usernames = document.querySelectorAll('.uoj-username');
const me = ['valor']; // Change it as you see fit!
const specified_users = ['ceba'];
usernames.forEach(username => {
const text = username.textContent;
if (text.length > 0) {
if (specified_users.includes(text)) {
const firstLetter = text.charAt(0);
const restOfText = text.slice(1);
username.innerHTML = `
<span style="font-size: 0;">
<span style="color: black; font-size: small;">${firstLetter}</span>
<span style="color: red; font-size: small;">${restOfText}</span>
</span>
`;
} else if (me.includes(text)) {
username.innerHTML = `
<span style="
background: linear-gradient(87deg, #5e72e4 0%, #825ee4 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
">
${text}
</span>
`;
}
}
});
// Find all elements with class .card-title under .card.border-info.mb-3
const cardTitles = document.querySelectorAll('.card.border-info.mb-3 .card-title');
// Iterate over each card title
cardTitles.forEach(cardTitle => {
// Check if the corresponding .sh_sourceCode element is present under the same parent
const CodeElement = cardTitle.closest('.card.border-info.mb-3').querySelector('code');
if (CodeElement) {
// Set the font size
cardTitle.style.fontSize = '1.75rem';
cardTitle.style.display = 'inline-block';
// Check how many .card-title elements have a corresponding .sh_sourceCode
const siblingCardTitles = Array.from(cardTitle.closest('.uoj-content').querySelectorAll('.card-title'))
.filter(title => title.closest('.card.border-info.mb-3').querySelector('code'));
// Set the inner text only if there's exactly one .card-title with a corresponding .sh_sourceCode
if (siblingCardTitles.length === 1) {
cardTitle.innerText = 'Source Code';
}
// Create the button
const button = document.createElement('button');
button.innerHTML = "<div class='exgf-copy'></div>"; // Optional: to use the SVG background
button.id = 'copyButton';
// Apply styles to the button
button.style.color = '#6c757d';
button.style.border = '0px solid #3498db';
button.style.marginLeft = '5px'; // Adjust margin as needed
button.style.fontSize = '0';
button.style.transition = 'background-color .3s';
button.style.backgroundImage = "url('data:image/svg+xml;utf8,<svg class=\"icon\" style=\"width: 1em;height: 1em;vertical-align: middle;fill: rgb(108, 117, 125);overflow: hidden;\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"2669\"><path d=\"M661.333333 234.666667A64 64 0 0 1 725.333333 298.666667v597.333333a64 64 0 0 1-64 64h-469.333333A64 64 0 0 1 128 896V298.666667a64 64 0 0 1 64-64z m-21.333333 85.333333H213.333333v554.666667h426.666667v-554.666667z m191.829333-256a64 64 0 0 1 63.744 57.856l0.256 6.144v575.701333a42.666667 42.666667 0 0 1-85.034666 4.992l-0.298667-4.992V149.333333H384a42.666667 42.666667 0 0 1-42.368-37.674666L341.333333 106.666667a42.666667 42.666667 0 0 1 37.674667-42.368L384 64h447.829333z\" p-id=\"2670\"></path></svg>')";
button.style.height = '20px';
button.style.width = '20px';
button.style.padding = '0';
button.style.display = 'inline-block'; // Ensure the button is inline
// Insert the button after the card title
cardTitle.parentNode.insertBefore(button, cardTitle.nextSibling);
// Add the click event listener for the button
button.addEventListener('click', function () {
const textToCopy = CodeElement.innerText; // Copy the text from the corresponding .sh_cpp element
const tempTextArea = document.createElement('textarea');
tempTextArea.value = textToCopy;
document.body.appendChild(tempTextArea);
tempTextArea.select();
document.execCommand('copy');
document.body.removeChild(tempTextArea);
});
}
});
const emoji_dic = {
'yiw': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'shuai': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'jy': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'zhm': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'shui': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'oh': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'hsh': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'zhq': 'https://s2.loli.net/2023/02/28/atHeX39NGlMfnYI.gif',
'kuk': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'tiao': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'qd': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'kx': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'my': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'll': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'gz': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'qiao': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'kk': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'cy': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'dz': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'gg': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'hanx': 'https://www.emojiall.com/img/platform/qq/[email protected]',
'fad': 'https://www.emojiall.com/img/platform/qq/[email protected]'
}
const name_dic = {
// put names here
// 'nick name': 'real name'
'吴尉华': '🐷',
'谢佳贤': '🐉',
'张乐涛': '🐢',
'戴恒飞': '😇',
'陈梓慠': '🤯',
'陆梓炀': '🦄',
'陆梓炀<sup>ℵ</sup>': '🦄',
'王孜研': '🕊',
'王孜研<sup>ℵ</sup>': '🕊',
'王诚俊': '🔨',
'陈诚': '🤡'
}
window.score_blocks = new Array()
window.name_blocks = new Array()
window.show_score = false
window.show_name = false
window.show_score = GM_getValue('_emojigfoj_show_score')
if (window.show_score === undefined) {
GM_setValue('_emojigfoj_show_score', window.show_score = false)
}
window.show_name = GM_getValue('_emojigfoj_show_name')
if (window.show_name === undefined) {
GM_setValue('_emojigfoj_show_name', window.show_name = false)
}
function extendScore(e) {
e.firstChild.style.width = '0pt'
e.lastChild.style.width = String(e.oldwidth) + 'pt'
}
function shrinkScore(e) {
if (window.show_score) return
e.firstChild.style.width = '20pt'
e.lastChild.style.width = '0pt'
}
function showName(e) {
e.innerHTML = e.realname
}
function showNick(e) {
e.innerHTML = e.nickname
}
function getScoreLevel(x) { // 0<=x<=1
if (x < 0) return 'yiw'
else if (x == 0) return 'my'
else if (x < 0.1) return 'shuai'
else if (x < 0.2) return 'qiao'
else if (x < 0.3) return 'shui'
else if (x < 0.4) return 'gg'
else if (x < 0.5) return 'oh'
else if (x < 0.6) return 'hsh'
else if (x < 0.7) return 'tiao'
else if (x < 0.8) return 'hanx'
else if (x < 0.9) return 'gz'
else if (x < 1.0) return 'kx'
else if (x == 1.0) return 'kuk'
else if (x > 1.0) return 'jy'
}
function newEmoji(url) { // create emoji element
var res = document.createElement('img')
res.className = "emoji"
res.src = url
return res
}
function newScoreBlock(score, emj) { // create score block element
var res = document.createElement('span')
res.oldwidth = score.offsetWidth
if (!window.show_score) {
score.style.width = '0pt'
}
else {
emj.style.width = '0pt'
score.style.width = res.oldwidth + 'pt'
}
res.style.width = Math.max(res.oldwidth, 20) + 'pt'
res.className = "score-block"
res.appendChild(emj)
res.innerHTML += score.outerHTML
res.onmouseover = function () { extendScore(res) }
res.onmouseleave = function () { shrinkScore(res) }
window.score_blocks.push(res)
return res
}
function newSwitch(id, text, func) { // create a new switch, call func(switch) when changed
var elem = document.createElement('label')
elem.className = 'dropdown-item option-label'
elem.setAttribute('for', id)
elem.innerHTML += '<input type="checkbox" id="' + id + '" class="custom-control-input">'
elem.innerHTML += '<div class="option-slider"></div>'
elem.innerHTML += '<span class="option-text">' + text + '</span>'
elem.addEventListener('change', function () {
func(document.getElementById(id))
})
return elem
}
function createOptionsDropdown() { // create options page
var elem = document.createElement('li')
elem.className = 'nav-item dropdown'
var toggle = document.createElement('a')
toggle.className = 'nav-link dropdown-toggle'
toggle.id = 'OptionsDropdown'
toggle.href = '#'
toggle.style = 'font-weight: bold'
toggle.setAttribute('data-toggle', 'dropdown')
toggle.setAttribute('aria-haspopup', 'true')
toggle.setAttribute('aria-expanded', 'false')
toggle.innerHTML = 'Extension'
elem.appendChild(toggle)
var menu = document.createElement('div')
menu.className = 'dropdown-menu'
menu.setAttribute('aria-labelledby', 'UserDropdown')
menu.appendChild(newSwitch('ScoreSwitch', 'Show Score', function (e) {
window.show_score = e.checked
GM_setValue('_emojigfoj_show_score', e.checked)
window.score_blocks.forEach(e.checked ? extendScore : shrinkScore)
}))
menu.appendChild(newSwitch('NameSwitch', 'Show Real Name', function (e) {
window.show_name = e.checked
GM_setValue('_emojigfoj_show_name', e.checked)
window.name_blocks.forEach(e.checked ? showName : showNick)
}))
elem.appendChild(menu)
var user = document.querySelector('#UserDropdown').parentNode
user.parentNode.insertBefore(elem, user)
document.getElementById('ScoreSwitch').checked = window.show_score
document.getElementById('NameSwitch').checked = window.show_name
}
createOptionsDropdown()
document.querySelectorAll('a[class="uoj-score"]').forEach(function (e) {
var max_score = 100
if (e.hasAttribute('data-max')) max_score = Number(e.getAttribute('data-max'))
var x = Number(e.innerHTML) / max_score
var url = ''
if (e.innerHTML == '97') url = emoji_dic.zhm
else url = emoji_dic[getScoreLevel(x)]
e.parentNode.insertBefore(newScoreBlock(e, newEmoji(url)), e)
e.remove()
})
document.querySelectorAll('a[class="small"]').forEach(function (e) {
var str = e.innerHTML
var url = null
if (str == 'Compile Error') url = emoji_dic.qd
else if (str == 'Waiting') url = emoji_dic.zhq
else if (str == 'Waiting Rejudge') url = emoji_dic.zhq
else if (str == 'Judging') url = emoji_dic.fad
if (url != null) e.parentNode.appendChild(newEmoji(url))
})
document.querySelectorAll('.uoj-username').forEach(function (e) {
e.nickname = e.innerHTML
e.realname = e.nickname
if (e.nickname in name_dic) {
e.realname = name_dic[e.nickname]
}
e.innerHTML = (window.show_name ? e.realname : e.nickname)
window.name_blocks.push(e)
})
var max_score_elem = document.querySelector('span[class="uoj-score"]')
if (max_score_elem != null) {
var max_score = Number(max_score_elem.innerHTML);
document.querySelectorAll('th').forEach(function (e) {
var str = ''
if (e.innerHTML == '总分') str = '赋分'
else if (e.innerHTML == 'Total Score') str = 'Relative Score'
else return
e.insertAdjacentHTML('afterend', '<th style="width:5em">' + str + '</th>')
})
document.querySelectorAll('span[class="uoj-score"]').forEach(function (e) {
var x = (max_score ? Number(e.innerHTML) / max_score : 0)
var url = emoji_dic[getScoreLevel(x)]
var str = String((x * 100).toFixed(2)) + '%'
var pa = e.parentElement
pa.insertBefore(newScoreBlock(e, newEmoji(url)), e)
pa.parentElement.insertAdjacentHTML('afterend', '<td style="width:5em; overflow: hidden">' + str + '</td>');
e.remove()
})
}
var sty = document.createElement('style')
sty.type = 'text/css'
sty.innerHTML = `
/* some css */
.emoji {
display: inline-block;
vertical-align: middle;
width: 20pt;
height: 20pt;
transition: width 0.5s;
}
.uoj-score {
display: inline-block;
vertical-align: middle;
overflow: hidden;
transition: width 0.5s;
}
.score-block {
display: inline-block;
white-space: nowrap;
height: 20pt;
}
.option-label {
margin: 0
}
.option-text {
vertical-align: middle;
}
.option-slider {
vertical-align: middle;
position: relative;
display: inline-block;
cursor: pointer;
width: 2em;
height: 1em;
margin-right: 5px;
border: #adb5bd solid 1px;
border-radius: .5em;
background: #ffffff;
transition: all 0.15s;
}
.option-slider::before {
position: absolute;
display: inline-block;
background: #adb5bd;
border-radius: .5em;
content: "";
height: calc(1em - 4px);
width: calc(1em - 4px);
left: 2px;
bottom: 1px;
transition: all 0.15s;
}
.custom-control-input:checked + .option-slider {
background: #007bff;
border: #007bff solid 1px;
}
.custom-control-input:checked + .option-slider::before {
background: #ffffff;
left: 1em;
}
`
document.head.appendChild(sty)
})();