Leetcode ProblemSet Stat Better Display

To better display Leetcode ProblemSet Stat; to hide and dismiss the locked problems.

Pada tanggal 05 Februari 2019. Lihat %(latest_version_link).

  1. // ==UserScript==
  2. // @name Leetcode ProblemSet Stat Better Display
  3. // @description To better display Leetcode ProblemSet Stat; to hide and dismiss the locked problems.
  4. // @version 0.2.1
  5. // @author pcm
  6. // @match https://leetcode.com/problemset/*
  7. // @match https://leetcode.com/tag/*
  8. // @run-at document-start
  9. // @grant GM_xmlhttpRequest
  10. // @connect leetcode.com
  11. // @require https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
  12. // @require https://greatest.deepsurf.us/scripts/5392-waitforkeyelements/code/WaitForKeyElements.js?version=115012
  13. // @namespace
  14. // ==/UserScript==
  15.  
  16. // some global configuration
  17. var CONF = {
  18. 'SVG_HEIGHT': 1000,
  19. 'SVG_WIDTH': 300,
  20. 'COLOR_AC': '#7bc96f',
  21. 'COLOR_NOTAC': '#08c',
  22. 'COLOR_TODO': '#ebedf0',
  23. 'CELL_HEIGHT': 10,
  24. 'CELL_WIDTH': 10,
  25. 'CELL_MARGIN': 2,
  26. 'CELL_W_COUNT': 25,
  27. }
  28.  
  29.  
  30. // if switchHideLockedProblems == true, hide all locked problems in problemset
  31. function statDifficulty(problemTable, switchHideLockedProblems, switchDrawProgressBar) {
  32. var res = {
  33. 'num_total_easy': 0,
  34. 'num_total_normal': 0,
  35. 'num_total_hard': 0,
  36. 'num_total': 0,
  37. 'num_ac_easy': 0,
  38. 'num_ac_normal': 0,
  39. 'num_ac_hard': 0,
  40. 'num_ac': 0,
  41. }
  42.  
  43. // find all related indices
  44. var index = {}
  45. var thead = problemTable.getElementsByTagName('thead')[0];
  46. var ths = thead.getElementsByTagName("th");
  47. for (var i = 0; i < ths.length; i++) {
  48. var th = ths[i];
  49. if (th.textContent == 'Difficulty') index.difficulty = i;
  50. if (th.textContent == '\xa0') index.status = i;
  51. if (th.textContent == 'Title') index.title = i;
  52. if (th.textContent == '#') index.id = i;
  53. }
  54. if (Object.keys(index).indexOf('status') == -1) index.status = 0;
  55. if (Object.keys(index).indexOf('id') == -1) index.id = 1;
  56.  
  57. var tbody = problemTable.getElementsByTagName('tbody')[0];
  58. var trs = tbody.getElementsByTagName("tr");
  59.  
  60. // make the ids of problemset ascendent
  61. var id1 = parseInt(trs[0].getElementsByTagName("td")[1].textContent);
  62. var thead_id = document.getElementsByClassName('reactable-th-question_id');
  63. if (!thead_id[0]) {
  64. thead_id = document.getElementsByClassName('reactable-th-id');
  65. }
  66. thead_id[0].click();
  67. var id2 = parseInt(trs[0].getElementsByTagName("td")[1].textContent);
  68. id1 = Math.min(id1, id2);
  69. if (parseInt(trs[0].getElementsByTagName("td")[1].textContent) != id1) {
  70. thead_id[0].click();
  71. }
  72.  
  73. for ( var j = 0; j < trs.length; j++) {
  74. var tds = trs[j].getElementsByTagName("td");
  75. var td_status = tds[index.status];
  76. var td_title = tds[index.title];
  77. var td_difficulty = tds[index.difficulty];
  78. var td_number = tds[index.id];
  79.  
  80. // dismiss locked problems
  81. var locked = td_title.getElementsByClassName('fa-lock');
  82. if (locked[0]) {
  83. if (switchHideLockedProblems) {
  84. trs[j].innerHTML = "";
  85. }
  86. continue;
  87. }
  88.  
  89. // stat difficulty
  90. var hard = td_difficulty.getElementsByClassName('label-danger');
  91. var normal = td_difficulty.getElementsByClassName('label-warning');
  92. var easy = td_difficulty.getElementsByClassName('label-success');
  93. var ac = td_status.getElementsByClassName('fa-check');
  94. var notac = td_status.getElementsByClassName('fa-question');
  95. if (switchDrawProgressBar) {
  96. var title = td_number.textContent + ' ' + td_title.firstChild.firstChild.textContent;
  97. drawOneCell(res.num_total, ac[0] ? true : false, notac[0] ? true : false, title);
  98. }
  99. if (hard[0]) {
  100. res.num_total_hard++;
  101. if (ac[0]) res.num_ac_hard++;
  102. }
  103. else if (normal[0]) {
  104. res.num_total_normal++;
  105. if (ac[0]) res.num_ac_normal++;
  106. }
  107. else if (easy[0]) {
  108. res.num_total_easy++;
  109. if (ac[0]) res.num_ac_easy++;
  110. }
  111. res.num_total++;
  112. if (ac[0]) res.num_ac++;
  113. }
  114. return res;
  115. }
  116.  
  117. function updateStatBar(welcomes) {
  118. var statBar = document.getElementById('welcome');
  119. if (!statBar) {
  120. var div = document.getElementsByClassName('header__2ZIe')[0];
  121. var p = div.getElementsByTagName('p')[1];
  122. p.innerHTML = '<div id="welcome"><span><span class="label label-primary round">Solved</span>&nbsp;-&nbsp;<span class="label label-success round"></span>&nbsp;<span class="label label-warning round"></span>&nbsp;<span class="label label-danger round"></span></span></div>';
  123. statBar = document.getElementById('welcome');
  124. }
  125. var total = statBar.getElementsByClassName('label-primary')[0];
  126. var hard = statBar.getElementsByClassName('label-danger')[0];
  127. var normal = statBar.getElementsByClassName('label-warning')[0];
  128. var easy = statBar.getElementsByClassName('label-success')[0];
  129.  
  130. total.textContent = welcomes.num_ac.toString() + '/' + welcomes.num_total.toString() + ' Solved';
  131. hard.textContent = 'Hard ' + welcomes.num_ac_hard.toString() + '/' + welcomes.num_total_hard.toString();
  132. normal.textContent = 'Medium ' + welcomes.num_ac_normal.toString() + '/' + welcomes.num_total_normal.toString();
  133. easy.textContent = 'Easy ' + welcomes.num_ac_easy.toString() + '/' + welcomes.num_total_easy.toString();
  134. }
  135.  
  136. function drawOneCell(i, ac, notac, title) {
  137. var svg = document.getElementById('gm_progress_graph');
  138. var x = (i % CONF.CELL_W_COUNT) * (CONF.CELL_MARGIN + CONF.CELL_WIDTH);
  139. var y = Math.floor(i / CONF.CELL_W_COUNT) * (CONF.CELL_MARGIN + CONF.CELL_HEIGHT);
  140. var color = CONF.COLOR_TODO;
  141. if (ac) color = CONF.COLOR_AC;
  142. else if (notac) color = CONF.COLOR_NOTAC;
  143.  
  144. var rectHTML =
  145. '<rect ' +
  146. 'width="' + CONF.CELL_WIDTH + '" ' +
  147. 'height="' + CONF.CELL_HEIGHT + '" ' +
  148. 'x="' + x.toString() + '" ' +
  149. 'y="' + y.toString() + '" ' +
  150. 'fill="' + color + '" ';
  151.  
  152. if (ac || notac) {
  153. rectHTML += '>' +
  154. '<title>' + title + '</title>' +
  155. '</rect>'
  156. }
  157. else {
  158. rectHTML += '/>';
  159. }
  160. svg.insertAdjacentHTML('beforeend', rectHTML);
  161. svg.setAttribute('height', y + (CONF.CELL_MARGIN + CONF.CELL_HEIGHT));
  162. }
  163.  
  164. function initDrawProgressGraph() {
  165. var div = document.getElementsByClassName('progress-panel-base');
  166. if (!div[0]) div = document.getElementsByClassName('header__2ZIe')[0];
  167. else div = div[0].firstChild;
  168. var svgHTML =
  169. '<div><svg ' +
  170. 'width="' + CONF.SVG_WIDTH + '" ' +
  171. 'height="' + CONF.SVG_HEIGHT + '" ' +
  172. 'id="gm_progress_graph" xmlns="http://www.w3.org/2000/svg"' +
  173. '>' +
  174. '<rect width="100%" height="100%" style="fill:white;/> ' +
  175. '</svg></div>'
  176. div.insertAdjacentHTML('afterend', svgHTML);
  177. return true;
  178. }
  179.  
  180. function init() {
  181. // document.getElementsByTagName('select')[0].options[3].selected = true;
  182. }
  183.  
  184. function changeStatInfo(jNode) {
  185. init();
  186. var problemTable = document.getElementsByClassName('question-list-table');
  187. if (!problemTable[0]) {
  188. problemTable = document.getElementsByClassName('table__XKyc');
  189. }
  190. if (problemTable[0]) {
  191. var switchHideLockedProblems = true;
  192. var switchDrawProgressBar = initDrawProgressGraph();
  193. var welcomes = statDifficulty(problemTable[0], switchHideLockedProblems, switchDrawProgressBar);
  194. updateStatBar(welcomes);
  195. }
  196. }
  197.  
  198. waitForKeyElements(".question-list-table", changeStatInfo)
  199. waitForKeyElements(".table__XKyc", changeStatInfo)