CF-rating-chart-patch

Some modification to make Codeforces rating chart better

  1. // ==UserScript==
  2. // @name CF-rating-chart-patch
  3. // @version 0.1.0
  4. // @description Some modification to make Codeforces rating chart better
  5. // @match *://codeforces.com/profile/*
  6. // @grant none
  7. // @run-at document-start
  8. // @namespace https://gf.qytechs.cn/users/410786
  9. // ==/UserScript==
  10. const oldCode = String.raw`
  11. grid: { hoverable: true, markings: markings }
  12. };
  13.  
  14. var plot = $.plot($("#placeholder"), datas, options);
  15.  
  16. function showTooltip(x, y, contents) {
  17. $('<div id="tooltip">' + contents + '</div>').css( {
  18. position: 'absolute',
  19. display: 'none',
  20. top: y - 20,
  21. left: x + 10,
  22. border: '1px solid #fdd',
  23. padding: '2px',
  24. 'font-size' : '11px',
  25. 'background-color': '#fee',
  26. opacity: 0.80
  27. }).appendTo("body").fadeIn(200);
  28. }
  29.  
  30. var ctx = plot.getCanvas().getContext("2d");
  31.  
  32. var prev = -1;
  33. $("#placeholder").bind("plothover", function (event, pos, item) {
  34. if (item) {
  35. if (prev != item.dataIndex) {
  36. $("#tooltip").remove();
  37. var params = data[item.seriesIndex][item.dataIndex];
  38.  
  39. var total = params[1];
  40. var change = params[5] > 0 ? "+" + params[5] : params[5];
  41. var contestName = params[11];
  42. var contestId = params[2];
  43. var contestUrl = params[7];
  44. var rank = params[6];
  45. var title = params[8];
  46. var html = "= " + total + " (" + change + "), " + title + "<br/>"
  47. + "Rank: " + rank + "<br/>"
  48. + "<a href='" + contestUrl + "'>" + contestName + "</a>";
  49. if (change > 0)
  50. html += "<br/><a style='font-weight: bold;' href=\"/bestRatingChanges/" + params[10] + "\">Share it!</a>";
  51. showTooltip(item.pageX, item.pageY, html);
  52. setTimeout(function () {
  53. $("#tooltip").fadeOut(200);
  54. prev = -1;
  55. }, 4000);
  56. prev = item.dataIndex;
  57. }
  58. }
  59. });`;
  60.  
  61. const newCode = '\ngrid: { hoverable: true, clickable: true, markings: markings } };' + (function(){
  62. // NOTE: toString does not work 100% of the time. Use String.raw instead if it doesn't work.
  63. var plot = $.plot($("#placeholder"), datas, options);
  64.  
  65. function showTooltip(x, y, contents) {
  66. $('<div id="tooltip">' + contents + '</div>').css( {
  67. position: 'absolute',
  68. display: 'none',
  69. top: y - 20,
  70. left: x,
  71. border: '1px solid #fdd',
  72. padding: '2px',
  73. 'font-size' : '11px',
  74. 'background-color': '#fee',
  75. opacity: 0.80
  76. }).appendTo("body").fadeIn(200);
  77. }
  78.  
  79. var ctx = plot.getCanvas().getContext("2d");
  80.  
  81. $("#placeholder").bind("plotclick", function (event, pos, item) {
  82. if (item) {
  83. var params = data[item.seriesIndex][item.dataIndex];
  84.  
  85. var total = params[1];
  86. var change = params[5] > 0 ? "+" + params[5] : params[5];
  87. var contestName = params[11];
  88. var contestId = params[2];
  89. var contestUrl = params[7];
  90. var rank = params[6];
  91. var title = params[8];
  92.  
  93. window.open(contestUrl)
  94. }
  95. });
  96.  
  97. var prev = -1;
  98. var tooltipFadeoutTimeoutId = null;
  99.  
  100. function clearTooltipFadeout () {
  101. if (tooltipFadeoutTimeoutId !== null)
  102. clearTimeout(tooltipFadeoutTimeoutId);
  103. }
  104.  
  105. function tooltipFadeout () {
  106. $("#tooltip").fadeOut(200);
  107. prev = -1;
  108. tooltipFadeoutTimeoutId = null;
  109. }
  110.  
  111. document.addEventListener('click', function (event) {
  112. if (event.target.id !== 'tooltip')
  113. tooltipFadeout();
  114. });
  115.  
  116. function setTooltipFadeout () {
  117. clearTooltipFadeout();
  118. tooltipFadeoutTimeoutId = setTimeout(tooltipFadeout, 4000);
  119. }
  120.  
  121. $("#placeholder").bind("plothover", function (event, pos, item) {
  122. if (item) {
  123. if (prev != item.dataIndex) {
  124. $("#tooltip").remove();
  125. var params = data[item.seriesIndex][item.dataIndex];
  126.  
  127. var total = params[1];
  128. var change = params[5] > 0 ? "+" + params[5] : params[5];
  129. var contestName = params[11];
  130. var contestId = params[2];
  131. var contestUrl = params[7];
  132. var rank = params[6];
  133. var title = params[8];
  134. var html = "= " + total + " (" + change + "), " + title + "<br/>"
  135. + "Rank: " + rank + "<br/>"
  136. + "<a href='" + contestUrl + "'>" + contestName + "</a>";
  137. if (change > 0)
  138. html += "<br/><a style='font-weight: bold;' href=\"/bestRatingChanges/" + params[10] + "\">Share it!</a>";
  139. showTooltip(item.pageX, item.pageY, html);
  140. prev = item.dataIndex;
  141.  
  142. $("#tooltip").bind("mouseenter", clearTooltipFadeout).bind("mouseleave", setTooltipFadeout);
  143. }
  144. } else {
  145. setTooltipFadeout();
  146. }
  147. }).bind("mouseleave", setTooltipFadeout);
  148. // this will always work because mouseleave of placeholder is fired before
  149. // mouseenter of tooltip (stackoverflow.com/q/10011493)
  150.  
  151. }).toString().replace(/}$/,'').replace(/^function.*?(\s*)\s*{/,'')
  152.  
  153.  
  154. var script_modified = false;
  155. new MutationObserver(function(mutations, observer){
  156. for (let r of mutations){
  157. let t=r.target
  158. if(t.tagName==='SCRIPT'){
  159. var ind = t.innerHTML.indexOf(oldCode);
  160. if (ind >= 0) {
  161. t.innerHTML = t.innerHTML.substr(0, ind) + newCode + t.innerHTML.substr(ind+oldCode.length)
  162. observer.disconnect();
  163. script_modified = true;
  164. console.log('CF script modified')
  165. return;
  166. }
  167. }
  168. }
  169. }).observe(document,{
  170. childList:true,
  171. subtree:true,
  172. });
  173.  
  174. window.addEventListener('load', function(){
  175. if (!script_modified)
  176. console.log('NOTE: script is not working')
  177. })

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址