AtCoderJudgeProgressColorizer

Colorize the progress of judge in AtCoder's submissions pages.

  1. // ==UserScript==
  2. // @name AtCoderJudgeProgressColorizer
  3. // @namespace https://satanic0258.github.io/
  4. // @version 1.0.0
  5. // @description Colorize the progress of judge in AtCoder's submissions pages.
  6. // @author satanic0258
  7. // @match https://atcoder.jp/contests/*/submissions*
  8. // @icon https://www.google.com/s2/favicons?domain=atcoder.jp
  9. // @grant none
  10. // @copyright 2021, satanic0258 (https://satanic0258.github.io/)
  11. // @license MIT License; https://opensource.org/licenses/MIT
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. function colorize(target) {
  18. const res = /(\d+)\/(\d+) (.*)?/.exec(target.innerText);
  19. if(res) {
  20. const ratio = (parseInt(res[1]) - 1) / parseInt(res[2]) * 100;
  21. const ratioStr = ratio + "%";
  22. const color = (res[3]) ? "#f0ad4e" : "#777"; // ? WA : WJ
  23. target.style.background = "linear-gradient(to right, "+color+" 0%, "+color+" "+ratioStr+", rgba(0,0,0,0) "+ratioStr+", rgba(0,0,0,0) 100%)";
  24. }
  25. }
  26.  
  27. // 変更があったら色付け
  28. const observer = new MutationObserver(records => {
  29. for(const record of records) {
  30. const target = record.target;
  31. if(target.tagName === "TD" && (target.classList.contains('waiting-judge') || target.id === "judge-status")){
  32. // WJ, 2/7, 2/7 WA,...
  33. colorize(target);
  34. }
  35. else if(target.tagName === "TR"){
  36. // ジャッジ終了時(提出一覧のみ)
  37. // 未定,正解/不正解の演出を入れるなどもできる
  38. }
  39. }
  40. });
  41.  
  42. // 監視対象の要素
  43. let observeTarget = null;
  44.  
  45. const url = window.location.href;
  46. if (url.match(new RegExp(/submissions\/(\d+)/)) != null) {
  47. // 個別の提出ページ
  48. const tables = document.getElementsByClassName("table");
  49. if(tables.length === 1) {
  50. // WJ中
  51. const td = document.getElementById("judge-status");
  52. colorize(td);
  53. observeTarget = td;
  54. }
  55. }
  56. else {
  57. // 提出一覧ページ
  58. const table = document.getElementsByClassName("table")[0];
  59. const thead = table.children[0];
  60. const baseLen = thead.children[0].children.length;
  61. const tbody = table.children[1];
  62.  
  63. // 読み込んだものを色付け
  64. for(const obj of tbody.children) {
  65. if(obj.children.length !== baseLen){
  66. colorize(obj.children[obj.children.length-2]);
  67. }
  68. }
  69. // tbodyを監視
  70. observeTarget = tbody;
  71. }
  72.  
  73. // 監視を開始
  74. if(observeTarget) {
  75. observer.observe(observeTarget, {
  76. childList: true,
  77. subtree: true
  78. });
  79. }
  80. })();