From c4c268fdf3e0e11945cba3b8c8b90a3c44fef208 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8C=97=E6=9E=81=E5=B0=8F=E7=8B=90?= <60805870+beijixiaohu@users.noreply.github.com> Date: Fri, 12 Jul 2024 10:45:49 +0800 Subject: [PATCH] =?UTF-8?q?fix(Codeforces):=20=E6=94=B9=E8=BF=9B"=E8=AF=84?= =?UTF-8?q?=E6=B5=8B=E7=8A=B6=E6=80=81=E6=96=87=E6=9C=AC=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?"=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=B7=BB=E5=8A=A0=20"inqueue"=20?= =?UTF-8?q?=E6=A0=87=E8=AF=86=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../locales/codeforces-better/settings.json | 2 +- script/dev/codeforces-better.user.js | 114 +++++++++++++++--- 2 files changed, 95 insertions(+), 21 deletions(-) diff --git a/resources/locales/codeforces-better/settings.json b/resources/locales/codeforces-better/settings.json index 8be49bb66..753f1c5eb 100644 --- a/resources/locales/codeforces-better/settings.json +++ b/resources/locales/codeforces-better/settings.json @@ -393,7 +393,7 @@ }, "judgeStatusReplaceText": { "title": "评测状态文本替换", - "helpText": "

将题目的评测状态文本替换为指定的文本。

支持的变量:

{Status} 评测结果的完整描述,例如 \"Accepted\"。

{Stat} 评测结果的缩写形式,例如 \"AC\"。

{Number} 评测结果中的最后一个数字,评测状态为AC时不显示。

{标识符:xxx} 当标识符为真时显示括号内的内容。支持的标识符:acwatlemlerecehackedskippedilepcpending

示例:

我怎么{Stat}了,{wa:呜呜}

此时如果评测结果为\"Wrong answer\",则会显示:

我怎么WA了,呜呜

", + "helpText": "

将题目的评测状态文本替换为指定的文本。

支持的变量:

{Status} 评测结果的完整描述,例如 \"Accepted\"。

{Stat} 评测结果的缩写形式,例如 \"AC\"。

{Number} 评测结果中的最后一个数字,评测状态为AC时不显示。

{标识符:xxx} 当标识符为真时显示括号内的内容。支持的标识符:acwatlemlerecehackedskippedilepcpendinginqueue

示例:

我怎么{Stat}了,{wa:呜呜}

此时如果评测结果为\"Wrong answer\",则会显示:

我怎么WA了,呜呜

", "placeholder": "请输入替换的模式,为空则不替换。" } }, diff --git a/script/dev/codeforces-better.user.js b/script/dev/codeforces-better.user.js index f26ca8e24..4186b817f 100644 --- a/script/dev/codeforces-better.user.js +++ b/script/dev/codeforces-better.user.js @@ -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/* @@ -6140,7 +6140,7 @@ const preference_settings_HTML = ` ${helpCircleHTML}
- + `; @@ -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", }; /** @@ -10233,7 +10235,8 @@ 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; @@ -10241,7 +10244,7 @@ async function judgeStatusReplace() { /** * 处理评测结果 - * @param {string} text 代替换的文本 + * @param {string} text 待替换的文本 * @returns {object} 处理后的文本和颜色 */ const process = (text) => { @@ -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); }); } });