StandingLikeCodeforces.js

順位表からCodeforcesのように提出を見れるようにするスクリプト

2021-05-10 يوللانغان نەشرى. ئەڭ يېڭى نەشرىنى كۆرۈش.

  1. // ==UserScript==
  2. // @name StandingLikeCodeforces.js
  3. // @namespace AtCoder
  4. // @version 0.1
  5. // @description 順位表からCodeforcesのように提出を見れるようにするスクリプト
  6. // @author Bondo
  7. // @match https://atcoder.jp/contests/*/standings
  8. // @require https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
  9. // ==/UserScript==
  10.  
  11. //HTMLの文字列をDocumentオブジェクトで返す
  12. function htmlStringToDocument(text){
  13. try{
  14. var dom_parser = new DOMParser();
  15. var document_obj = dom_parser.parseFromString(text , "text/html");
  16. if(document_obj.getElementsByTagName("parsererror").length == 0){
  17. return document_obj;
  18. }
  19. }catch(e){
  20. }
  21.  
  22. try{
  23. var document_obj = document.implementation.createHTMLDocument("");
  24. document_obj.body.innerHTML = text;
  25. return document_obj;
  26. }catch(e){
  27. }
  28.  
  29. return null;
  30. }
  31.  
  32.  
  33. $(function(){
  34. //順位表ページのURL
  35. var standingURL = location.href;
  36. //ベースのURL https://atcoder.jp/contest/*/
  37. var baseURL = standingURL.replace('standings','');
  38. var taskURL = baseURL + 'tasks/';
  39. var allSubmissionsURL = baseURL + 'submissions/';
  40.  
  41. //問題の数
  42. var numberOfProblems = 0;
  43. //問題名の配列 ex)abc141_a
  44. var nameOfProblems = [];
  45.  
  46. //問題一覧を取得する
  47. $.ajax({
  48. url: allSubmissionsURL, // 表示させたいコンテンツがあるページURL
  49. type: 'GET',
  50. datatype: 'html',
  51. async : false,
  52. }).done(function(html){
  53. var submissionsHtml = htmlStringToDocument(html);
  54. var problems = $('#select-task', submissionsHtml).children();
  55. numberOfProblems = problems.length;
  56. for(var i=0;i<numberOfProblems;i++){
  57. if(i == 0) continue;
  58. var problem = problems.eq(i).val()
  59. //提出一覧を初期化
  60. nameOfProblems.push(problem);
  61. }
  62. });
  63.  
  64. setTimeout(
  65. function () {
  66. //順位表の列を取得
  67. //const trs = document.querySelector("#standings-tbody tr");
  68. //const table = $("#main-container > div.row > div:nth-child(3) > div.panel.panel-default.panel-standings > div.table-responsive > table");
  69. var table = document.getElementById('standings-tbody');
  70.  
  71. for(var tr=0;tr<table.rows.length;tr++){
  72. //お気に入りユーザの名前
  73. var username = '';
  74. //お気に入りユーザの提出URLを入れる辞書
  75. var submissions = {};
  76. //ユーザがお気に入りかどうか
  77. var fav = false;
  78. for(var td=0;td<table.rows[tr].cells.length;td++){
  79. var cells = table.rows[tr].cells[td];
  80. //alert(td + cells.innerHTML);
  81. if(td == 1){
  82. //alert(td + cells.innerHTML);
  83. var imgSrc = cells.getElementsByClassName('fav-btn-standings')[0].src;
  84. //お気に入りユーザの場合
  85. if(imgSrc.search('unfav') < 0){
  86. //お気に入りユーザ名
  87. username = cells.getElementsByClassName('username')[0].innerText;
  88. fav = true;
  89. //お気に入りユーザの提出一覧ページのURL
  90. var queryParameters = `submissions?f.Status=AC&f.User=${username}`;
  91. var newURL = baseURL + queryParameters;
  92. //ユーザの提出一覧ページを取得する
  93. $.ajax({
  94. url: newURL, // 表示させたいコンテンツがあるページURL
  95. type: 'GET',
  96. datatype: 'html',
  97. async: false,//同期通信
  98. }).done(function(html){
  99. //提出ページのHTMLの文字列を取得し,documentにする
  100. var submissionsHtml = htmlStringToDocument(html);
  101. //提出一覧のTableを取得
  102. var submissionsTable = submissionsHtml.querySelector("#main-container > div.row > div:nth-child(3) > div.panel.panel-default.panel-submission > div.table-responsive > table > tbody")
  103. //お気に入りユーザの提出一覧を初期化する
  104. for(var i=0;i<numberOfProblems;i++){
  105. submissions[nameOfProblems[i]] = 'null';
  106. }
  107. for(var subtr=0;subtr<submissionsTable.rows.length;subtr++){
  108. //問題のkeyを取得 ex)abs141_a
  109. var task = submissionsTable.rows[subtr].cells[1].getElementsByTagName('a')[0].href;
  110. //提出のURLを取得
  111. var submissionURL = submissionsTable.rows[subtr].cells[9].getElementsByTagName('a')[0].href
  112. //keyのみにする
  113. task = task.replace(taskURL, '');
  114. //提出の新しい順に辞書に追加していく 既に入っていればそのまま
  115. if(submissions[task] == 'null'){
  116. submissions[task] = submissionURL;
  117. }
  118. }
  119. //Object.keys(submissions).map(key => alert(key + ' ' + submissions[key]));
  120. });
  121. }
  122. }
  123. if(3 <= td && td < 3 + numberOfProblems - 1 && fav){
  124. var cellsHtml = cells.getElementsByTagName('p')[0].innerHTML;
  125. var link = submissions[nameOfProblems[td-3]];
  126. //ACの提出があればリンクを貼る
  127. if(link != 'null'){
  128. cells.getElementsByTagName('p')[0].innerHTML = '<a href=' + link + '>' + cellsHtml + '</a>';
  129. }
  130. //<td class="standings-result"><p>-</p></td>
  131. //<td class="standings-result"><p><span class="standings-ac">500</span></p><p>48:18</p></td>
  132. }
  133. }
  134. }
  135. },
  136. "2000"
  137. );
  138. });