Skip to content

Commit

Permalink
fix(Codeforces): 改进"评测状态文本替换"功能,添加 "inqueue" 标识符
Browse files Browse the repository at this point in the history
  • Loading branch information
beijixiaohu committed Jul 12, 2024
1 parent 60ed517 commit c4c268f
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 21 deletions.
2 changes: 1 addition & 1 deletion resources/locales/codeforces-better/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@
},
"judgeStatusReplaceText": {
"title": "评测状态文本替换",
"helpText": "<p>将题目的评测状态文本替换为指定的文本。</p><p>支持的变量:</p><p><strong><code>{Status}</code></strong> 评测结果的完整描述,例如 \"Accepted\"。</p><p><strong><code>{Stat}</code></strong> 评测结果的缩写形式,例如 \"AC\"。</p><p><strong><code>{Number}</code></strong> 评测结果中的最后一个数字,评测状态为AC时不显示。</p><p><strong><code>{标识符:xxx}</code> </strong>当标识符为真时显示括号内的内容。支持的标识符:<code>ac</code>、<code>wa</code>、<code>tle</code>、<code>mle</code>、<code>re</code>、<code>ce</code>、<code>hacked</code>、<code>skipped</code>、<code>ile</code>、<code>pc</code>、<code>pending</code></p><div style=\"border: 1px solid #795548; padding: 10px;\"><p>示例:</p><p><code>我怎么{Stat}了,{wa:呜呜}</code></p><p>此时如果评测结果为\"Wrong answer\",则会显示:<p></p>我怎么WA了,呜呜</p></div>",
"helpText": "<p>将题目的评测状态文本替换为指定的文本。</p><p>支持的变量:</p><p><strong><code>{Status}</code></strong> 评测结果的完整描述,例如 \"Accepted\"。</p><p><strong><code>{Stat}</code></strong> 评测结果的缩写形式,例如 \"AC\"。</p><p><strong><code>{Number}</code></strong> 评测结果中的最后一个数字,评测状态为AC时不显示。</p><p><strong><code>{标识符:xxx}</code> </strong>当标识符为真时显示括号内的内容。支持的标识符:<code>ac</code>、<code>wa</code>、<code>tle</code>、<code>mle</code>、<code>re</code>、<code>ce</code>、<code>hacked</code>、<code>skipped</code>、<code>ile</code>、<code>pc</code>、<code>pending</code>、<code>inqueue</code></p><div style=\"border: 1px solid #795548; padding: 10px;\"><p>示例:</p><p><code>我怎么{Stat}了,{wa:呜呜}</code></p><p>此时如果评测结果为\"Wrong answer\",则会显示:<p></p>我怎么WA了,呜呜</p></div>",
"placeholder": "请输入替换的模式,为空则不替换。"
}
},
Expand Down
114 changes: 94 additions & 20 deletions script/dev/codeforces-better.user.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// ==UserScript==
// @name Codeforces Better!
// @namespace https://greasyfork.org/users/747162
// @version 1.76.5
// @version 1.76.6
// @author 北极小狐
// @match *://*.codeforces.com/*
// @match *://*.codeforc.es/*
Expand Down Expand Up @@ -6140,7 +6140,7 @@ const preference_settings_HTML = `
${helpCircleHTML}
<div class="tip_text" data-i18n="[html]settings:preference.judgeStatusReplaceText.helpText"></div>
</div>
<input type="text" id='judgeStatusReplaceText' class='no_default' data-i18n="[placeholder]settings:preference.judgeStatusReplaceText.placeholder">
<textarea type="text" id='judgeStatusReplaceText' class='no_default' data-i18n="[placeholder]settings:preference.judgeStatusReplaceText.placeholder"></textarea>
</div>
</div>
`;
Expand Down Expand Up @@ -10106,16 +10106,18 @@ const StatusAcronyms = {
"Idleness limit exceeded": "ILE",
"Perfect result:": "AC",
"Partial result:": "PC",
"Running": "PENDING"
"Running": "PENDING",
"In queue": "INQUEUE"
};

/**
* 评测结果的颜色
*/
const StatusColors = {
"AC": "#52c41a",
"AC": "#0a0",
"WA": "#e74c3c",
"PENDING": "#808080",
"INQUEUE": "#808080",
};

/**
Expand Down Expand Up @@ -10233,15 +10235,16 @@ async function judgeStatusReplace() {
skipped: statusAcronym === "Skipped",
ile: statusAcronym === "ILE",
pc: statusAcronym === "PC",
pending: statusAcronym === "PENDING"
pending: statusAcronym === "PENDING",
inqueue: statusAcronym === "INQUEUE",
}
const final_result = parseTemplate(result, statusMap);
return final_result;
};

/**
* 处理评测结果
* @param {string} text 代替换的文本
* @param {string} text 待替换的文本
* @returns {object} 处理后的文本和颜色
*/
const process = (text) => {
Expand All @@ -10264,26 +10267,97 @@ async function judgeStatusReplace() {
OJB_observeElement({
selector: '.datatable',
callback: (node) => {
/**
* 更新元素
* @param {HTMLElement} element - 要更新的元素
*/
const updateElement = (element) => {
const { text, color } = process($(element).text());
$(element).text(text);
$(element).css({
"color": color,
"font-weight": "700"
});

/**
* 替换文本并着色
* @param {HTMLElement} element - 要处理的元素
*/
const replaceAndColor = (element) => {
const { text, color } = process(element.textContent);
element.textContent = text;
element.style.color = color;
element.style.fontWeight = '700';
};

/**
* 获取最小目标元素
* @param {HTMLElement} element - 要检查的元素
* @returns {HTMLElement} - 最小目标元素
*/
const getMinElement = (element) => {
// 先获取一次text值
const { text: originalText } = process(element.textContent);

/**
* 深搜
* @param {HTMLElement} el - 当前遍历的元素
* @returns {HTMLElement} - 能维持text不变的最小子元素
*/
const findMinElement = (el) => {
// 遍历子元素
for (let child of el.children) {
// 获取子元素的处理后的text值
const { text: childText } = process(child.textContent);

// 如果子元素的text与原始text相同,递归检查子元素
if (childText === originalText) {
return findMinElement(child);
}
}

// 如果没有子元素能维持text不变,返回当前元素
return el;
};

// 从初始元素开始递归
return findMinElement(element);
};

// 获取最小目标元素
const minElement = getMinElement(element);
// 替换文本并着色
replaceAndColor(minElement);
};

// 选择器
const selectorCondition = "[class^='verdict-'], [submissionverdict='COMPILATION_ERROR']";
/**
* 判断该元素是否在 .status-verdict-cell 内,
* 检查直到确认是或者遇到了 .datatable 或没有上层元素
*
* @param {Element} element - 要检查的元素
* @returns {Element|null} - 如果是,则返回对应的 .status-verdict-cell 元素,否则返回 null
* @throws {TypeError} - 如果提供的值不是有效的 DOM 元素
*/
const isDescendantOfStatusVerdictCell = (element) => {
if (!(element instanceof Element)) {
throw new TypeError('The provided value is not a valid DOM element.');
}

let currentElement = element;

while (currentElement && !currentElement.matches('.datatable')) {
if (currentElement.matches('.status-verdict-cell')) {
return currentElement;
}
currentElement = currentElement.parentElement;
}

return null;
};

// 检查[node]本身是否符合选择器条件
if ($(node).is(selectorCondition)) {
updateElement(node);
// 检查变动元素是否在 .status-verdict-cell 内
const statusVerdictCell = isDescendantOfStatusVerdictCell(node);
if (statusVerdictCell) {
updateElement(statusVerdictCell);
}

// 更新[node]内部符合选择器条件的所有元素
$(node).find(selectorCondition).each(function () {
updateElement(this);
// 检查node内部所有的 .status-verdict-cell 元素
node.querySelectorAll('.status-verdict-cell').forEach(element => {
updateElement(element);
});
}
});
Expand Down

0 comments on commit c4c268f

Please sign in to comment.