atcoder-problem-navigator

Shows a navigation bar on AtCoder and Codeforces contest pages for jumping to problems.

Versión del día 07/12/2019. Echa un vistazo a la versión más reciente.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

  1. // ==UserScript==
  2. // @name atcoder-problem-navigator
  3. // @namespace https://github.com/yoshrc
  4. // @version 1.3
  5. // @description Shows a navigation bar on AtCoder and Codeforces contest pages for jumping to problems.
  6. // @author yoshrc
  7. // @include https://atcoder.jp/contests/*
  8. // @include https://codeforces.com/contest/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. const KEY_PREFIX = 'atcoder-problem-navigator-';
  16.  
  17. const do_atcoder = () => {
  18. const contest = location.href.match(/^https:\/\/atcoder\.jp\/contests\/([^\/?]+)/)[1];
  19. const key = KEY_PREFIX + 'atcoder-' + contest;
  20.  
  21. if (location.href.match(/^https:\/\/atcoder\.jp\/contests\/([^\/]+)\/tasks\/?$/)) {
  22. const problems = [];
  23. const rows = document.querySelectorAll('tbody>tr');
  24. for (let i = 0; i < rows.length; i++) {
  25. const links = rows[i].querySelectorAll('a');
  26. const href = links[0].getAttribute('href');
  27. const text = links[0].textContent + ' - ' + links[1].textContent;
  28. problems.push({
  29. href: href,
  30. text: text
  31. });
  32. }
  33. localStorage[key] = JSON.stringify(problems);
  34. }
  35.  
  36. if (key in localStorage) {
  37. let problems = JSON.parse(localStorage[key]);
  38. const problemsBar = document.createElement('ul');
  39. problemsBar.className = 'nav nav-tabs';
  40. for (let i = 0; i < problems.length; i++) {
  41. const link = document.createElement('a');
  42. link.setAttribute('style', 'margin-left: 10px; margin-right: 10px; white-space: nowrap');
  43. link.setAttribute('href', problems[i].href);
  44. link.textContent = problems[i].text;
  45. const span = document.createElement('span');
  46. span.textContent = ' ';
  47. span.appendChild(link);
  48. problemsBar.appendChild(span);
  49. }
  50. document.getElementById('contest-nav-tabs').appendChild(problemsBar);
  51. }
  52. };
  53.  
  54. const do_codeforces = () => {
  55. const contest = location.href.match(/^https:\/\/codeforces\.com\/contest\/([^\/?]+)/)[1];
  56. const key = KEY_PREFIX + 'codeforces-' + contest;
  57.  
  58. if (location.href.match(/^https:\/\/codeforces\.com\/contest\/([^\/]+)\/?$/)) {
  59. const problems = [];
  60. const rows = document.querySelectorAll('.problems>tbody>tr');
  61. // Starts from 1 to skip the header
  62. for (let i = 1; i < rows.length; i++) {
  63. const links = rows[i].querySelectorAll('a');
  64. const href = links[0].getAttribute('href');
  65. const text = links[0].textContent + '. ' + links[1].textContent;
  66. problems.push({
  67. href: href,
  68. text: text
  69. });
  70. }
  71. localStorage[key] = JSON.stringify(problems);
  72. }
  73.  
  74. if (key in localStorage) {
  75. let problems = JSON.parse(localStorage[key]);
  76. const problemsBar = document.createElement('ul');
  77. problemsBar.setAttribute('style', 'margin-left: 15px; margin-right: 280px; padding-top: 30px');
  78. for (let i = 0; i < problems.length; i++) {
  79. const link = document.createElement('a');
  80. link.setAttribute('style', 'margin-right: 20px; white-space: nowrap');
  81. link.setAttribute('href', problems[i].href);
  82. link.textContent = problems[i].text;
  83. const span = document.createElement('span');
  84. span.textContent = ' ';
  85. span.appendChild(link);
  86. problemsBar.appendChild(span);
  87. }
  88.  
  89. const content = document.getElementById('pageContent');
  90. content.parentNode.insertBefore(problemsBar, content);
  91. }
  92. };
  93.  
  94. if (location.href.match(/^https:\/\/atcoder\.jp\/contests\//)) {
  95. do_atcoder();
  96. } else if (location.href.match(/^https:\/\/codeforces\.com\/contest\//)) {
  97. do_codeforces();
  98. }
  99. })();