Skip to content

Instantly share code, notes, and snippets.

@wizicer
Last active December 18, 2025 17:37
Show Gist options
  • Select an option

  • Save wizicer/3edf35044f1c8461608804580c2d3954 to your computer and use it in GitHub Desktop.

Select an option

Save wizicer/3edf35044f1c8461608804580c2d3954 to your computer and use it in GitHub Desktop.
ICASSP Review Score Annotator
// ==UserScript==
// @name ICASSP Review Score Annotator
// @namespace https://icassp-exact-score
// @version 0.4
// @description Annotate ICASSP reviews with exact scores strictly following the rubric
// @match https://cmsworkshops.com/ICASSP2026/papers/author_response.php*
// @grant none
// ==/UserScript==
(function () {
'use strict';
// 规则按“更具体的短语优先”排序,避免子串误匹配
const SCORE_RULES = [
// Q1
{ key: 'Clearly out of scope', score: 0 },
{ key: 'Scope relevance is marginal', score: 1 },
{ key: 'Clearly within scope', score: 2 },
// Q2
{ key: 'Technically sound without any identifiable', score: 4 },
{ key: 'Some minor concerns', score: 3 },
{ key: 'Moderate concerns', score: 2 },
{ key: 'Major errors', score: 1 },
// Q3
{ key: 'Highly novel', score: 4 },
{ key: 'Substantial novelty', score: 3 },
{ key: 'Moderate novelty', score: 2 },
{ key: 'Limited novelty', score: 1 },
{ key: 'Not novel', score: 0 },
// Q4
{ key: 'Sufficient validation', score: 3 },
{ key: 'Limited but convincing', score: 2 },
{ key: 'Lacking in some respect', score: 1 },
{ key: 'Insufficient validation', score: 0 },
// Q5
{ key: 'Highly significant', score: 5 },
{ key: 'Substantial contribution', score: 4 },
{ key: 'Moderate contribution', score: 3 },
{ key: 'Insufficient contribution', score: 2 },
{ key: 'Limited contribution', score: 1 },
{ key: 'Insignificant contribution', score: 0 },
// Q6
{ key: 'Complete list of references without any significant omissions', score: 3 },
{ key: 'A largely complete list of references', score: 2 },
{ key: 'Some significant omissions', score: 1 },
{ key: 'One or more major omissions', score: 0 },
// Q7
{ key: 'All references are directly relevant', score: 3 },
{ key: 'Some of the references are of limited relevance', score: 2 },
{ key: 'Some of the references are clearly irrelevant', score: 1 },
{ key: 'A significant number of references are clearly irrelevant', score: 0 },
// Q8
{ key: 'Well-structured and clearly written', score: 4 },
{ key: 'Some minor structural', score: 3 },
{ key: 'Moderate issues of exposition', score: 2 },
{ key: 'Serious structural, language', score: 1 },
{ key: 'incomprehensible', score: 0 },
];
function getScoreFromCellText(text) {
const t = text.trim();
for (const rule of SCORE_RULES) {
if (t.includes(rule.key)) return rule.score;
}
return null;
}
function isReviewerCard(card) {
const header = card.querySelector('.card-header');
if (!header) return false;
// 仅处理 reviewer 卡:header 有 "Reviewer" 且包含 badge,且不是 "Reviewers"
const headerText = header.textContent || '';
if (!headerText.includes('Reviewer')) return false;
if (headerText.includes('Reviewers')) return false;
const hasBadge = !!header.querySelector('.badge');
if (!hasBadge) return false;
// reviewer 的 header 在你的页面是 bg-dark(示例中如此),再加一道过滤更稳
if (!header.classList.contains('bg-dark')) return false;
return true;
}
document.querySelectorAll('.card').forEach(card => {
if (!isReviewerCard(card)) return;
const header = card.querySelector('.card-header');
const cells = card.querySelectorAll('.cms-bg-review');
let total = 0;
// 先计算 total,不依赖是否已经注入过
const scoredCells = [];
cells.forEach(cell => {
if (cell.closest('pre')) return; // comments
const text = cell.innerText || '';
const score = getScoreFromCellText(text);
if (score !== null) {
total += score;
scoredCells.push({ cell, score });
}
});
// 再注入每项分数(幂等)
scoredCells.forEach(({ cell, score }) => {
if (cell.dataset.scored === 'true') return;
cell.dataset.scored = 'true';
cell.innerHTML = `<strong>[${score}]</strong> ` + cell.innerHTML;
});
// 在 reviewer header 后追加总分(幂等)
if (header && header.dataset.totalAdded !== 'true') {
header.dataset.totalAdded = 'true';
header.innerHTML +=
` <span style="margin-left:8px;color:#ffd966;font-weight:bold;">(Total: ${total})</span>`;
}
});
})();
@debugAllTheTime
Copy link

debugAllTheTime commented Dec 18, 2025

// ==UserScript==
// @name         ICASSP Review Score Annotator
// @namespace    https://icassp-exact-score
// @version      0.5
// @description  Annotate ICASSP reviews with exact scores strictly following the rubric
// @match        https://cmsworkshops.com/ICASSP2026/papers/author_response.php*
// @grant        none
// ==/UserScript==

(function () {
  'use strict';

  // 规则按"更具体的短语优先"排序,避免子串误匹配
  // 每条规则增加 maxScore 表示该项的总分
  const SCORE_RULES = [
    // Q1 (满分 2)
    { key: 'Clearly out of scope', score:  0, maxScore: 2 },
    { key: 'Scope relevance is marginal', score: 1, maxScore:  2 },
    { key: 'Clearly within scope', score: 2, maxScore:  2 },

    // Q2 (满分 4)
    { key: 'Technically sound without any identifiable', score: 4, maxScore: 4 },
    { key: 'Some minor concerns', score: 3, maxScore: 4 },
    { key: 'Moderate concerns', score: 2, maxScore:  4 },
    { key: 'Major errors', score: 1, maxScore: 4 },

    // Q3 (满分 4)
    { key: 'Highly novel', score: 4, maxScore: 4 },
    { key: 'Substantial novelty', score: 3, maxScore:  4 },
    { key: 'Moderate novelty', score:  2, maxScore: 4 },
    { key:  'Limited novelty', score:  1, maxScore: 4 },
    { key: 'Not novel', score: 0, maxScore: 4 },

    // Q4 (满分 3)
    { key: 'Sufficient validation', score: 3, maxScore: 3 },
    { key: 'Limited but convincing', score: 2, maxScore:  3 },
    { key: 'Lacking in some respect', score: 1, maxScore: 3 },
    { key: 'Insufficient validation', score: 0, maxScore:  3 },

    // Q5 (满分 5)
    { key: 'Highly significant', score: 5, maxScore: 5 },
    { key: 'Substantial contribution', score: 4, maxScore: 5 },
    { key: 'Moderate contribution', score: 3, maxScore: 5 },
    { key: 'Insufficient contribution', score: 2, maxScore:  5 },
    { key: 'Limited contribution', score: 1, maxScore: 5 },
    { key: 'Insignificant contribution', score: 0, maxScore: 5 },

    // Q6 (满分 3)
    { key: 'Complete list of references without any significant omissions', score:  3, maxScore: 3 },
    { key:  'A largely complete list of references', score: 2, maxScore: 3 },
    { key: 'Some significant omissions', score:  1, maxScore: 3 },
    { key:  'One or more major omissions', score: 0, maxScore: 3 },

    // Q7 (满分 3)
    { key: 'All references are directly relevant', score: 3, maxScore: 3 },
    { key: 'Some of the references are of limited relevance', score: 2, maxScore: 3 },
    { key: 'Some of the references are clearly irrelevant', score: 1, maxScore: 3 },
    { key: 'A significant number of references are clearly irrelevant', score: 0, maxScore: 3 },

    // Q8 (满分 4)
    { key: 'Well-structured and clearly written', score: 4, maxScore:  4 },
    { key: 'Some minor structural', score: 3, maxScore: 4 },
    { key: 'Moderate issues of exposition', score: 2, maxScore: 4 },
    { key: 'Serious structural, language', score: 1, maxScore: 4 },
    { key: 'incomprehensible', score: 0, maxScore: 4 },
  ];

  // 计算所有项目的总分上限 (2+4+4+3+5+3+3+4 = 28)
  const MAX_TOTAL = 2 + 4 + 4 + 3 + 5 + 3 + 3 + 4;

  function getScoreFromCellText(text) {
    const t = text. trim();
    for (const rule of SCORE_RULES) {
      if (t.includes(rule.key)) {
        return { score: rule.score, maxScore: rule.maxScore };
      }
    }
    return null;
  }

  function isReviewerCard(card) {
    const header = card.querySelector('.card-header');
    if (!header) return false;

    // 仅处理 reviewer 卡:header 有 "Reviewer" 且包含 badge,且不是 "Reviewers"
    const headerText = header.textContent || '';
    if (!headerText.includes('Reviewer')) return false;
    if (headerText.includes('Reviewers')) return false;

    const hasBadge = !!header. querySelector('.badge');
    if (!hasBadge) return false;

    // reviewer 的 header 在你的页面是 bg-dark(示例中如此),再加一道过滤更稳
    if (!header.classList. contains('bg-dark')) return false;

    return true;
  }

  document.querySelectorAll('.card').forEach(card => {
    if (!isReviewerCard(card)) return;

    const header = card.querySelector('.card-header');
    const cells = card.querySelectorAll('.cms-bg-review');

    let total = 0;

    // 先计算 total,不依赖是否已经注入过
    const scoredCells = [];
    cells. forEach(cell => {
      if (cell.closest('pre')) return; // comments
      const text = cell.innerText || '';
      const result = getScoreFromCellText(text);
      if (result !== null) {
        total += result.score;
        scoredCells.push({ cell, score: result.score, maxScore: result. maxScore });
      }
    });

    // 再注入每项分数(幂等),显示格式为 [得分/该项总分]
    scoredCells.forEach(({ cell, score, maxScore }) => {
      if (cell.dataset.scored === 'true') return;
      cell.dataset. scored = 'true';
      cell. innerHTML = `<strong>[${score}/${maxScore}]</strong> ` + cell.innerHTML;
    });

    // 在 reviewer header 后追加总分(幂等),显示格式为 (Total: 得分/总分)
    if (header && header. dataset.totalAdded !== 'true') {
      header. dataset.totalAdded = 'true';
      header.innerHTML +=
        ` <span style="margin-left:8px;color:#ffd966;font-weight:bold;">(Total: ${total}/${MAX_TOTAL})</span>`;
    }
  });
})();

这个在小分处也会显示这个小份的最高分数

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment