atcoder-virtual-remaining-time-display

バーチャルコンテストの残り時間を表示します。

Verze ze dne 10. 12. 2022. Zobrazit nejnovější verzi.

  1. // ==UserScript==
  2. // @name atcoder-virtual-remaining-time-display
  3. // @namespace https://github.com/ilplrr
  4. // @version 1.0
  5. // @description バーチャルコンテストの残り時間を表示します。
  6. // @author ilplrr
  7. // @license MIT
  8. // @match https://atcoder.jp/contests/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. const createTimer = (data) => {
  16. if (!data.isVirtual) return;
  17. if (!(data.virtualStartTime && data.virtualEndTime)) return;
  18.  
  19. const timer = document.createElement('div');
  20. timer.id = 'virtual-timer';
  21. timer.style = `
  22. position: fixed;
  23. right: 170px;
  24. bottom: 0px;
  25. width: 160px;
  26. height: 80px;
  27. margin: 0;
  28. padding: 20px 0;
  29. background-image: url("//img.atcoder.jp/assets/contest/digitalclock.png");
  30. text-align: center;
  31. line-height: 20px;
  32. font-size: 15px;
  33. cursor: pointer;
  34. z-index: 50;
  35. `;
  36. document.body.appendChild(timer);
  37.  
  38. let intervalId = null;
  39. const update = () => {
  40. const serverTime = getServerTime();
  41. let s = '';
  42. if (serverTime.isAfter(data.virtualEndTime)) {
  43. s += 'バーチャル参加終了<br>'
  44. s += `<span style="color: #c00;">残り:${durationFormat(0)}</span>`;
  45. if (intervalId) {
  46. clearInterval(intervalId);
  47. intervalId = null;
  48. }
  49. } else if (serverTime.isAfter(data.virtualStartTime)) {
  50. s += 'バーチャル参加中<br>'
  51. s += `残り:${durationFormat(data.virtualEndTime.diff(serverTime))}`;
  52. } else {
  53. s += 'バーチャル参加まで<br>'
  54. s += `残り:${durationFormat(data.virtualStartTime.diff(serverTime))}`;
  55. }
  56. timer.innerHTML = s;
  57. };
  58. intervalId = setInterval(update, 100);
  59. };
  60.  
  61. const virtualStandingURL = `${location.origin}/contests/${contestScreenName}/standings/virtual`;
  62. fetch(virtualStandingURL).then((response) => {
  63. return response.text();
  64. }).then((text) => {
  65. const doc = new DOMParser().parseFromString(text, 'text/html');
  66. const data = {};
  67. doc.querySelectorAll('script').forEach((e) => {
  68. const s = e.innerHTML;
  69. const m = s.match(/(isVirtual|virtual(Start|End)Time)\s*=\s*[^\n]*/g);
  70. if (m) {
  71. m.forEach((s) => eval('data.' + s));
  72. }
  73. });
  74. createTimer(data);
  75. });
  76. })();