AtCoder - You're top X%

Displays your approximate ranking percentile among all active AtCoder users on your profile page.

Version au 05/10/2024. Voir la dernière version.

  1. // ==UserScript==
  2. // @name AtCoder - You're top X%
  3. // @namespace https://gist.github.com/k1832/9438a1469bb2fa94d26702e1556aff97
  4. // @version 1.0
  5. // @description Displays your approximate ranking percentile among all active AtCoder users on your profile page.
  6. // @author k1832
  7. // @match https://atcoder.jp/users/*
  8. // @license MIT License, Copyright (c) 2024 Keita Morisaki
  9. // @grant GM_xmlhttpRequest
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. 'use strict';
  14.  
  15. const url = new URL(window.location.href);
  16. const contestType = url.searchParams.get('contestType');
  17.  
  18. if (contestType === 'algo' || contestType === null) {
  19. /*
  20. * EN: Fetch the total number of active AtCoder users from a JSON file hosted on GitHub.
  21. * JA: GitHub でホストされている JSON ファイルから、AtCoder のアクティブユーザーの総数を取得します。
  22. */
  23. GM_xmlhttpRequest({
  24. method: "GET",
  25. url: "https://k1832.github.io/atcoder-api/api/v1/total-active-users.json",
  26. onload: function (response) {
  27. const data = JSON.parse(response.responseText);
  28. const totalCount = data.val;
  29.  
  30. let rankNode = document.evaluate(
  31. '//th[text()="順位" or text()="Rank"]/following-sibling::td',
  32. document,
  33. null,
  34. XPathResult.ANY_TYPE,
  35. null
  36. ).iterateNext();
  37.  
  38. if (!rankNode) {
  39. console.error('Ranking element not found.');
  40. return;
  41. }
  42.  
  43. const rankText = rankNode.textContent;
  44.  
  45. // "8956th" -> 8956
  46. const rank = parseInt(rankText.slice(0, -2), 10);
  47. const percentage = rank / totalCount * 100;
  48. rankNode.textContent += ` (top ${percentage.toFixed(2)}%)`;
  49. },
  50. onerror: function (error) {
  51. console.error('Error fetching user count:', error);
  52. }
  53. });
  54. }
  55. })();