AnkiWeb Quiz

Shows quiz on ankiweb.

目前为 2023-10-01 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name AnkiWeb Quiz
  3. // @namespace https://greasyfork.org/users/102866
  4. // @description Shows quiz on ankiweb.
  5. // @match https://ankiuser.net/*
  6. // @match https://ankiweb.net/*
  7. // @author TiLied
  8. // @version 2.0.02
  9. // @grant GM_listValues
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM_deleteValue
  13. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
  14. // @grant GM.listValues
  15. // @grant GM.getValue
  16. // @grant GM.setValue
  17. // @grant GM.deleteValue
  18. // ==/UserScript==
  19.  
  20. class AnkiWebQuiz
  21. {
  22. _Options = new Object();
  23. _Decks = new Object();
  24. _GlobalId = 0;
  25.  
  26. _DeckId;
  27.  
  28. constructor()
  29. {
  30. //GM.deleteValue("awqDecks");
  31. //GM.deleteValue("awqGlobalId");
  32. console.log("AnkiWeb Quiz v" + GM.info.script.version + " initialization");
  33.  
  34. this._LoadOptionsAndDecks();
  35. this._SetCSS();
  36. }
  37.  
  38. _SetCSS()
  39. {
  40. globalThis.window.document.head.append("<!--Start of AnkiWeb Quiz v" + GM.info.script.version + " CSS-->");
  41. globalThis.window.document.head.insertAdjacentHTML("beforeend", "<style type='text/css'>div.awq_quizGrid" +
  42. "{" +
  43. "display: grid;" +
  44. "grid-template-columns: repeat(4,auto);" +
  45. "grid-template-rows: auto;" +
  46. "}</style>");
  47.  
  48. globalThis.window.document.head.insertAdjacentHTML("beforeend", "<style type='text/css'>div.awq_quizButton" +
  49. "{" +
  50. "color: #fff;" +
  51. "background-color: #0275d8;" +
  52. "border-color: #0275d8;" +
  53. "padding: .75rem 1.5rem;" +
  54. "font-size: 1rem;" +
  55. "border-radius: .3rem;" +
  56. "border: 1px solid transparent;" +
  57. "max-width:250px;" +
  58. "margin:5px;" +
  59. "cursor: pointer;" +
  60. "max-height: 300px;" +
  61. "overflow: auto;" +
  62. "}</ style >");
  63. globalThis.window.document.head.insertAdjacentHTML("beforeend", "<style type='text/css'>div.awq_quizButton:hover" +
  64. "{" +
  65. "background-color: #025aa5;" +
  66. "}</ style >");
  67.  
  68. globalThis.window.document.head.insertAdjacentHTML("beforeend", "<style type='text/css'>div.awq_true" +
  69. "{" +
  70. "background-color: #75d802;" +
  71. "}</style>");
  72. globalThis.window.document.head.insertAdjacentHTML("beforeend", "<style type='text/css'>div.awq_true:hover" +
  73. "{" +
  74. "background-color: #5aa502;" +
  75. "}</style>");
  76. globalThis.window.document.head.insertAdjacentHTML("beforeend", "<style type='text/css'>.awq_trueBorder" +
  77. "{" +
  78. "border-color: #75d802;" +
  79. "border-width: 3px;" +
  80. "}</style>");
  81. globalThis.window.document.head.insertAdjacentHTML("beforeend", "<style type='text/css'>div.awq_false" +
  82. "{" +
  83. "background-color: #d80275;" +
  84. "}</style>");
  85. globalThis.window.document.head.insertAdjacentHTML("beforeend", "<style type='text/css'>div.awq_false:hover" +
  86. "{" +
  87. "background-color: #a5025a;" +
  88. "}</style>");
  89. globalThis.window.document.head.insertAdjacentHTML("beforeend", "<style type='text/css'>.awq_falseBorder" +
  90. "{" +
  91. "border-color: #d80275;" +
  92. "border-width: 3px;" +
  93. "}</style>");
  94.  
  95. globalThis.window.document.head.append("<!--End of AnkiWeb Quiz v" + GM.info.script.version + " CSS-->");
  96.  
  97. }
  98.  
  99. async _LoadOptionsAndDecks()
  100. {
  101. this._Options = await GM.getValue("awqOptions");
  102. this._Decks = await GM.getValue("awqDecks");
  103. this._GlobalId = await GM.getValue("awqGlobalId");
  104.  
  105. if (this._Options == null)
  106. this._Options = new Object();
  107. if (this._Decks == null)
  108. this._Decks = new Object();
  109. if (this._GlobalId == null)
  110. this._GlobalId = 0;
  111.  
  112. //Console log prefs with value
  113. console.log("*prefs:");
  114. console.log("*-----*");
  115.  
  116. let vals = await GM.listValues();
  117.  
  118. for (let i = 0; i < vals.length; i++)
  119. {
  120. console.log("*" + vals[i] + ":" + await GM.getValue(vals[i]));
  121. }
  122. console.log("*-----*");
  123. }
  124.  
  125. async Main()
  126. {
  127. if (globalThis.window.document.location.pathname.startsWith("/decks"))
  128. {
  129. let strs = globalThis.window.document.querySelectorAll("button.btn-link");
  130. for (let i = 0; i < strs.length; i++)
  131. {
  132. let _node = strs[i];
  133. let _text = _node.textContent.trim().replaceAll(" ", "");
  134.  
  135. if(this._Decks[_text] == null)
  136. this._Decks[_text] = new Object();
  137.  
  138. _node.addEventListener("click", () =>
  139. {
  140. GM.setValue("awqDeckId", _text);
  141. }, true);
  142.  
  143. }
  144. GM.setValue("awqDecks", this._Decks);
  145. }
  146. if (globalThis.window.document.location.pathname.startsWith("/study"))
  147. {
  148. this._DeckId = await GM.getValue("awqDeckId");
  149. if (this._DeckId == null)
  150. {
  151. console.log("Deck id is null");
  152. return;
  153. }
  154.  
  155. let _awq = globalThis.window.document.body.querySelector("#qa");
  156. console.log(_awq);
  157.  
  158. if (_awq == null)
  159. {
  160. globalThis.window.setTimeout(() =>
  161. {
  162. this.Main();
  163. }, 1000);
  164. return;
  165. }
  166. let _inner = _awq.innerHTML;
  167. let _id = "";
  168. let keys = Object.keys(this._Decks[this._DeckId]);
  169. for (let i = 0; i < keys.length; i++)
  170. {
  171. if (_inner == this._Decks[this._DeckId][keys[i]]["question"])
  172. {
  173. _id = this._Decks[this._DeckId][keys[i]]["cardId"];
  174. break;
  175. }
  176. }
  177.  
  178. if (_id == "")
  179. {
  180. _id += this.GetId();
  181.  
  182. this._Decks[this._DeckId][_id] = new Object();
  183. this._Decks[this._DeckId][_id]["cardId"] = _id;
  184. this._Decks[this._DeckId][_id]["question"] = _inner;
  185. this._Decks[this._DeckId][_id]["answer"] = "Use this deck more!";
  186. }
  187.  
  188. this.Qiuz(_id);
  189.  
  190. GM.setValue("awqDecks", this._Decks);
  191. }
  192. }
  193.  
  194. Qiuz(id)
  195. {
  196. this.PlayAudio();
  197.  
  198. let cardsId = new Array();
  199.  
  200. cardsId.push(id);
  201.  
  202. let keys = Object.keys(this._Decks[this._DeckId]);
  203.  
  204. let len = 11;
  205. if(len >= keys.length)
  206. {
  207. len = keys.length- 1;
  208. }
  209.  
  210. for(let i = 0; i < len; i++)
  211. {
  212. let _randomInt = this.GetRandomInt(keys.length);
  213. let _id = keys[_randomInt];
  214. let _continue = false;
  215.  
  216. for (let j = 0; j < cardsId.length; j++)
  217. {
  218. if (_id == cardsId[j])
  219. {
  220. i--;
  221. _continue = true;
  222. break;
  223. }
  224. }
  225. if (_continue)
  226. continue;
  227. else
  228. cardsId.push(_id);
  229. }
  230. //Console.WriteLine(cardsId);
  231.  
  232. cardsId = this.Shuffle(cardsId);
  233.  
  234. let before = globalThis.window.document.querySelector("#qa_box");
  235. let divGrid = globalThis.window.document.createElement("div");
  236. divGrid.classList.add("awq_quizGrid");
  237.  
  238. before.parentNode.insertBefore(divGrid, before);
  239.  
  240. let answer = globalThis.window.document.querySelector("button.btn-primary");
  241. if (!answer.classList.contains("awqEvent"))
  242. {
  243. answer.classList.add("awqEvent");
  244. answer.addEventListener("click", () =>
  245. {
  246. let eases = globalThis.window.document.querySelectorAll("#easebuts button");
  247.  
  248. //Console.WriteLine(eases);
  249. for (let i = 0; i < eases.length; i++)
  250. {
  251. if (eases[i].classList.contains("awqEvent"))
  252. continue;
  253.  
  254. eases[i].classList.add("awqEvent");
  255. eases[i].addEventListener("click", () =>
  256. {
  257. this.AddEventsForEases();
  258. }, false);
  259. }
  260. }, false);
  261. }
  262.  
  263. for (let i = 0; i < cardsId.length; i++)
  264. {
  265. let div = globalThis.window.document.createElement("div");
  266. div.classList.add("awq_quizButton");
  267. div.id = cardsId[i];
  268.  
  269. div.addEventListener("click", (e) =>
  270. {
  271. let _id = e.currentTarget.id;
  272. console.log(_id);
  273.  
  274. let _button = globalThis.window.document.querySelector("button.btn-primary");
  275. _button.click();
  276.  
  277. let _awq = globalThis.window.document.body.querySelector("#qa");
  278. this._Decks[this._DeckId][id]["answer"] = _awq.innerHTML;
  279. this.PlayAudio();
  280.  
  281. globalThis.window.setTimeout(() =>
  282. {
  283. let _eases = globalThis.window.document.querySelectorAll("button.m-1");
  284.  
  285. //Console.WriteLine(_eases);
  286. for (let i = 0; i < _eases.length; i++)
  287. {
  288. if (_eases[i].classList.contains("awqEvent"))
  289. continue;
  290.  
  291. _eases[i].classList.add("awqEvent");
  292. _eases[i].addEventListener("click", () =>
  293. {
  294. this.AddEventsForEases();
  295. }, false);
  296. }
  297.  
  298. if (_id == id)
  299. {
  300. div.classList.add("awq_true");
  301. div.classList.add("awq_trueBorder");
  302.  
  303. _eases[1].classList.add("awq_trueBorder");
  304. }
  305. else
  306. {
  307. div.classList.add("awq_false");
  308. div.classList.add("awq_falseBorder");
  309.  
  310. _eases[0].classList.add("awq_falseBorder");
  311. }
  312. }, 500);
  313. },false);
  314.  
  315. let q = this._Decks[this._DeckId][cardsId[i]]["question"].replace("</awq>", "");
  316. let html = "<awq>" + this._Decks[this._DeckId][cardsId[i]]["answer"].replace(q, "").replace("\n\n<hr id=\"answer\">\n\n", "").replace("<img", "<img width=\"100%\"");
  317.  
  318. div.insertAdjacentHTML("beforeend", html);
  319.  
  320. divGrid.append(div);
  321. }
  322. }
  323.  
  324. AddEventsForEases()
  325. {
  326. let grid = globalThis.window.document.querySelector(".awq_quizGrid");
  327. grid.remove();
  328. this.Main();
  329. }
  330.  
  331. GetId()
  332. {
  333. let id = this._GlobalId++;
  334. GM.setValue("awqGlobalId", id);
  335. return id;
  336. }
  337.  
  338. PlayAudio()
  339. {
  340. let box = globalThis.window.document.body.querySelector("#qa_box");
  341. if (box != null)
  342. {
  343. let audio = box.querySelector("audio");
  344. if(audio != null)
  345. audio.play();
  346. }
  347. }
  348.  
  349. GetRandomInt(max)
  350. {
  351. return Math.floor(Math.random() * max);
  352. }
  353.  
  354. Shuffle(array)
  355. {
  356. for (let i = array.length- 1; i > 0; i--)
  357. {
  358. let _i = i + 1;
  359. let j = Math.floor(Math.random() * _i);
  360. let temp = array[i];
  361. array[i] = array[j];
  362. array[j] = temp;
  363. }
  364.  
  365. return array;
  366. }
  367. }
  368.  
  369.  
  370. let awq;
  371.  
  372. window.onload = function ()
  373. {
  374. awq = new AnkiWebQuiz();
  375.  
  376. setTimeout(() =>
  377. {
  378. awq.Main();
  379. console.log(awq);
  380. }, 1000);
  381. };