AtCoder 中文助手

在英文题面前显示 AtCoder 中文题面。

  1. // ==UserScript==
  2. // @name AtCoder 中文助手
  3. // @namespace Violentmonkey Scripts
  4. // @match https://atcoder.jp/contests/*/tasks/*
  5. // @grant none
  6. // @license MIT
  7. // @version 3.3.1
  8. // @author Acfboy, psz2007
  9. // @description 在英文题面前显示 AtCoder 中文题面。
  10. // ==/UserScript==
  11.  
  12. function readTextFile(file, ext, callback) {
  13. let xhr = new XMLHttpRequest();
  14. xhr.overrideMimeType("application/" + ext);
  15. xhr.open("GET", file, false);
  16. xhr.onreadystatechange = function () {
  17. if (xhr.readyState === 4){
  18. callback(xhr.responseText, xhr.status);
  19. }
  20. }
  21. xhr.send();
  22. }
  23.  
  24. function getPoints() {
  25. let cur = document.getElementsByClassName('lang-ja')[0].childNodes[1].innerHTML;
  26. if(cur.indexOf("配点") == -1){
  27. return "";
  28. }else{
  29. return cur.replace("配点", "分值").replace("点", "分");
  30. }
  31. }
  32.  
  33. let url = window.location.href, contId = url.split('/')[4], probId = url.split('/')[6], traId = "",
  34. traList = [], failFlg = 0, notFoundFlg = 0, src = ""
  35. readTextFile("https://atcoder-for-chinese-developers.github.io/translations/list.json", "json", function(txt, stat){
  36. if(stat == 200){
  37. traList = JSON.parse(txt).data
  38. }else{
  39. alert("翻译列表加载失败")
  40. failFlg = 1
  41. }
  42. })
  43.  
  44. if(!failFlg){
  45. if(!(contId in traList) || !(probId in traList[contId])){
  46. failFlg = notFoundFlg = 1
  47. }else{
  48. for(let i in traList[contId][probId]){
  49. traId = i
  50. }
  51. readTextFile("https://atcoder-for-chinese-developers.github.io/translations/" + contId + "." + probId + "." + traId + ".html", "html", function(txt, stat){
  52. if(stat == 200){
  53. src = txt
  54. }else{
  55. alert("翻译加载失败")
  56. failFlg = 1
  57. }
  58. })
  59. }
  60. }
  61.  
  62. let script = document.createElement('script');
  63. script.setAttribute('type', 'text/javascript');
  64. script.innerText = 'function showChn() {\
  65. document.getElementsByClassName("lang-en")[0].style = "display: none";\
  66. document.getElementsByClassName("lang-ja")[0].style = "display: none";\
  67. document.getElementsByClassName("lang-cn")[0].style = "display: inline";\
  68. }\
  69. function showEng() {\
  70. document.getElementsByClassName("lang-en")[0].style = "display: inline";\
  71. document.getElementsByClassName("lang-ja")[0].style = "display: none";\
  72. document.getElementsByClassName("lang-cn")[0].style = "display: none";\
  73. }\
  74. function showJpn() {\
  75. document.getElementsByClassName("lang-en")[0].style = "display: none";\
  76. document.getElementsByClassName("lang-ja")[0].style = "display: inline";\
  77. document.getElementsByClassName("lang-cn")[0].style = "display: none";\
  78. }'
  79. document.getElementsByTagName('head')[0].appendChild(script);
  80.  
  81. let isOldCont = document.getElementById("task-statement").childElementCount > 1;
  82.  
  83. if(document.getElementById("task-statement").childNodes[1].getAttribute("id") != null){
  84. isOldCont = 1
  85. document.getElementById("task-statement").innerHTML = document.getElementById("task-statement").childNodes[1].innerHTML
  86. }
  87.  
  88. if(isOldCont){
  89. document.getElementById("task-lang-btn").setAttribute("style","display: block;")
  90. document.getElementById("task-lang-btn").innerHTML=document.getElementById("task-lang-btn").innerHTML.replace(" / ", "")
  91. document.getElementById("task-lang-btn").innerHTML=document.getElementById("task-lang-btn").innerHTML.replace("<span data-lang=\"ja\">", "<span onclick=\"showJpn()\" data-lang=\"ja\">")
  92. document.getElementById("task-lang-btn").innerHTML=document.getElementById("task-lang-btn").innerHTML.replace("<span data-lang=\"en\">", "<span style=\"display: none;\" data-lang=\"en\">")
  93. let langSpan = document.createElement('span'),
  94. jaSta = document.getElementById("task-statement").innerHTML,
  95. jaSpan = document.createElement("span"),
  96. enSpan = document.createElement("span")
  97. enSpan.setAttribute("class", "lang-en")
  98. jaSpan.setAttribute("class", "lang-ja")
  99. jaSpan.setAttribute("style", "display: inline;")
  100. jaSpan.innerHTML = jaSta
  101. langSpan.setAttribute("class", "lang")
  102. langSpan.appendChild(jaSpan)
  103. langSpan.appendChild(enSpan)
  104. document.getElementById("task-statement").innerHTML="";
  105. document.getElementById("task-statement").appendChild(langSpan);
  106. }
  107.  
  108. let allBtn = document.getElementById('task-lang-btn'), chnBtn = document.createElement('span');
  109. chnBtn.setAttribute('data-lang', 'cn')
  110. chnBtn.innerHTML = ' / <img src=\"//img.atcoder.jp/assets/flag/CN.png\">'
  111. chnBtn.setAttribute('onclick', 'showChn()')
  112. allBtn.appendChild(chnBtn)
  113.  
  114. let cnSpan = document.createElement('span')
  115. cnSpan.setAttribute('class', 'lang-cn')
  116.  
  117. if(notFoundFlg){
  118. cnSpan.innerHTML = "暂无中文题面,欢迎<a href=\"https://github.com/atcoder-for-chinese-developers/atcoder-for-chinese\">贡献</a>!"
  119. }else if(failFlg){
  120. cnSpan.innerHTML = "翻译加在过程中出现错误,请刷新界面并重试。"
  121. }else{
  122. cnSpan.innerHTML = getPoints() + src;
  123. }
  124.  
  125. document.getElementsByClassName('lang')[0].appendChild(cnSpan)