CF-Predictor

This extension predicts rating changes for Codeforces. It shows approximate deltas during and after the contest.

当前为 2021-06-11 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name CF-Predictor
  3. // @version 1.3.1
  4. // @description This extension predicts rating changes for Codeforces. It shows approximate deltas during and after the contest.
  5. // @author Originally by WslF, Edited by ZZYSonny
  6. // @match *://codeforces.com/contest/*/standings*
  7. // @match *://codeforc.es/contest/*/standings*
  8. // @match *://codeforces.ml/contest/*/standings*
  9. // @connect cf-predictor-frontend.herokuapp.com
  10. // @connect cf-predictor.herokuapp.com
  11. // @grant GM_xmlhttpRequest
  12. // @namespace https://greasyfork.org/users/169007
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17. var partyNum = 0;
  18. var results = [];
  19. showDeltas();
  20.  
  21. function modifyPartyHtml(index, elem) {
  22. var delta = '?';
  23. var rank = ' ';
  24. var seed = ' ';
  25.  
  26. if (partyNum > 0) {
  27. var handle = $(elem).find("td:eq(1)").find("a").last().html();
  28. if (handle) {
  29. //next 2 lines - fix for legendary grandmaster
  30. handle = handle.replace('<span class="legendary-user-first-letter">','');
  31. handle = handle.replace('</span>','');
  32. if (handle in results) {
  33. delta = results[handle].delta;
  34. rank = results[handle].rank;
  35. seed = results[handle].seed;
  36. }
  37. }
  38. }
  39.  
  40. var darkClass = "";
  41. if (partyNum % 2 == 1) {
  42. darkClass = "dark ";
  43. }
  44. var text;
  45. if (partyNum == 0) {
  46. text = "<th class='top right' style='width: 4em;'><span title='Rating change''>&Delta;</span></th>";
  47. } else {
  48. if (delta > 0) {
  49. text = "<td class='" + darkClass + "right'><span style='color:green;font-weight:bold;'>+" + delta + "</span></td>";
  50. } else {
  51. text = "<td class='" + darkClass + "right'><span style='color:gray;font-weight:bold;'>" + delta + "</span></td>";
  52. }
  53. }
  54.  
  55. partyNum++;
  56. $(elem).append(text);
  57. /*
  58. text = "<td class='" + darkClass + "right'><span style='color:green;'>" + rank + "</span></td>";
  59. $(elem).append(text);
  60. text = "<td class='" + darkClass + "right'><span style='color:green;'>" + seed + "</span></td>";
  61. $(elem).append(text);
  62. */
  63. }
  64.  
  65. function showDeltas() {
  66. var count = $(".standings").find("tr").length;
  67. if (count > 2) {
  68. var contestId = document.location.href.replace(/\D+/ig, ',').substr(1).split(',')[0];
  69. var contestants = document.getElementsByClassName("contestant-cell");
  70. var contestantsHandles = Array.from(contestants).map(x => x.innerText.trim());
  71.  
  72. getDeltas(contestId, contestantsHandles, function() {
  73. $(".standings").find("tr").first().find("th").last().removeClass("right");
  74. $(".standings").find("tr").find("td").removeClass("right");
  75. $(".standings").find("tr").each(modifyPartyHtml);
  76. if (count % 2 == 0) {
  77. $(".standings").find("tr").last().find("td").last().replaceWith("<td class='smaller bottom right dark'>&Delta;</td>");
  78. } else {
  79. $(".standings").find("tr").last().find("td").last().replaceWith("<td class='smaller bottom right'>&Delta;</td>");
  80. }
  81. });
  82. }
  83. }
  84.  
  85. function parseDeltas(data, callback) {
  86. for (var i = 0; i < data.result.length; i++) {
  87. var handle = data.result[i].handle;
  88. var delta = data.result[i].newRating - data.result[i].oldRating;
  89. var rank = data.result[i].rank;
  90. var seed = data.result[i].seed;
  91.  
  92. var res = {
  93. delta : parseInt(delta),
  94. seed : parseInt(seed),
  95. rank : parseInt(rank)
  96. };
  97.  
  98. results[handle] = res;
  99. }
  100.  
  101. callback();
  102. }
  103.  
  104. function getDeltas(contestId, contestantsHandles, callback) {
  105. // var localServer = "http://localhost:8080/"
  106. var herokuServerOld = "https://cf-predictor-frontend.herokuapp.com/";
  107. var pageOld = "GetNextRatingServlet?contestId=" + contestId;
  108. var serverOld = herokuServerOld + pageOld;
  109.  
  110. var herokuServerNew = "https://cf-predictor.herokuapp.com/";
  111. var pageNew = "GetPartialRatingChangesServlet?contestId=" + contestId + "&handles="+contestantsHandles.join(",");
  112. var serverNew = herokuServerNew + pageNew;
  113.  
  114. try{
  115. GM_xmlhttpRequest({
  116. method: "GET",
  117. url: serverNew,
  118. onload: function(res) {
  119. var text = res.responseText;
  120. var data = JSON.parse(text);
  121. parseDeltas(data, callback);
  122. }
  123. });
  124. }catch(err){
  125. console.log(err);
  126. try{
  127. GM_xmlhttpRequest({
  128. method: "GET",
  129. url: serverOld,
  130. onload: function(res) {
  131. var text = res.responseText;
  132. var data = JSON.parse(text);
  133. parseDeltas(data, callback);
  134. }
  135. });
  136. }catch(err){
  137. console.log(err);
  138. }
  139. }
  140. }
  141. })();