Greasy Fork is available in English.

Better Statsbar (LeetCode)

Show the total number of questions per difficulty in LeetCode's statsbar.

  1. // ==UserScript==
  2. // @name Better Statsbar (LeetCode)
  3. // @description Show the total number of questions per difficulty in LeetCode's statsbar.
  4. // @namespace https://greatest.deepsurf.us/en/users/128831-marvinyan
  5. // @match https://leetcode.com/problemset/*
  6. // @grant GM.getValue
  7. // @grant GM.setValue
  8. // @grant GM_getValue
  9. // @grant GM_setValue
  10. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
  11. // @require https://greatest.deepsurf.us/scripts/374849-library-onelementready-es6/code/Library%20%7C%20onElementReady%20ES6.js?version=649483
  12. // @version 0.0.1.20190110053516
  13. // ==/UserScript==
  14.  
  15. (() => {
  16. const BASE_URL_LC = 'https://leetcode.com/api/problems/';
  17. const CACHE_DURATION_MS = 0 * 1000; // Optional rate limit (default: 0s)
  18. const CURRENT_TIME_MS = new Date().getTime();
  19.  
  20. const getData = async () => {
  21. const problemCategory = window.location.pathname.split('/')[2];
  22. const url = BASE_URL_LC + problemCategory;
  23.  
  24. const lastCheck = await GM.getValue('lastCheck', Number.MAX_VALUE);
  25. const cachedJsonStr = await GM.getValue('cachedJsonStr', null);
  26. const timeSinceCheck = CURRENT_TIME_MS - lastCheck;
  27.  
  28. return new Promise(resolve => {
  29. if (timeSinceCheck < CACHE_DURATION_MS && cachedJsonStr !== null) {
  30. resolve(cachedJsonStr);
  31. } else {
  32. const xhr = new XMLHttpRequest();
  33. xhr.open('GET', url, true);
  34. xhr.onload = () => {
  35. if (xhr.status >= 200 && xhr.status < 300) {
  36. GM.setValue('lastCheck', CURRENT_TIME_MS);
  37. GM.setValue('cachedJsonStr', xhr.responseText);
  38. resolve(xhr.responseText);
  39. }
  40. };
  41. xhr.send();
  42. }
  43. });
  44. };
  45.  
  46. const parseData = response => {
  47. const counts = [0, 0, 0];
  48. const questions = JSON.parse(response).stat_status_pairs;
  49.  
  50. questions.forEach(q => {
  51. counts[q.difficulty.level - 1]++;
  52. });
  53.  
  54. return counts;
  55. };
  56.  
  57. const updateStatsBar = counts => {
  58. const statsBar = $('#welcome > span > span');
  59.  
  60. let $totalSolvedSpan = $(statsBar[0]).closest('span');
  61. const newText = $totalSolvedSpan.text().replace('/', ' / ');
  62. $totalSolvedSpan.text(newText);
  63.  
  64. for (let i = 1; i < statsBar.length; i++) {
  65. statsBar[i].append(` / ${counts[i - 1]}`);
  66. }
  67. };
  68.  
  69. const run = async () => {
  70. const data = await getData();
  71. const counts = parseData(data);
  72. updateStatsBar(counts);
  73. };
  74.  
  75. waitForKeyElements('#welcome', run);
  76. })();