AnkiWeb Quiz

Shows quiz on ankiweb

当前为 2017-03-17 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name AnkiWeb Quiz
  3. // @namespace https://greasyfork.org/users/102866
  4. // @description Shows quiz on ankiweb
  5. // @include https://ankiweb.net/*
  6. // @include http://ankiweb.net/*
  7. // @require https://code.jquery.com/jquery-3.1.1.min.js
  8. // @author TiLied
  9. // @version 0.1.0
  10. // @grant GM_getResourceText
  11. // @grant GM_listValues
  12. // @grant GM_deleteValue
  13. // @grant GM_getValue
  14. // @grant GM_setValue
  15. // @resource ankiDeck Japanese.txt
  16. // ==/UserScript==
  17.  
  18. var originAnkiDeck = GM_getResourceText("ankiDeck");
  19. var stringArray = [];
  20. var tempStrings = [];
  21. var searchFor;
  22. var trueAnswer;
  23. var falseAnswers = [];
  24. var inB = [];
  25. var inE = [];
  26. var inBstring = "<awq>";
  27. var inEstring = "</awq>";
  28. var inBegAnswer = "<awq_answer>";
  29. var inEndAnswer = "</awq_answer>";
  30. var trueId, id;
  31. var buttons = [];
  32. var tempArr = [];
  33. var debug;
  34. var rubyVal;
  35. var amountButtons;
  36.  
  37.  
  38. Main();
  39.  
  40. function Main()
  41. {
  42. inB = findIndexes(inBstring, originAnkiDeck);
  43. inE = findIndexes(inEstring, originAnkiDeck);
  44. console.log(inB);
  45. console.log(inE);
  46.  
  47. for (var i = 0; i < inB.length; i++)
  48. {
  49. tempStrings[i] = originAnkiDeck.slice(inB[i] + 5, inE[i]);
  50. //console.log(tempStrings[i]);
  51. }
  52. console.log(tempStrings);
  53. cssAdd();
  54. //setSettings();
  55. }
  56.  
  57. //Settings
  58. function setSettings()
  59. {
  60. const settings = $("<li class=nav-item></li>").html("<a id=awq_settings class=nav-link>Settings Ankiweb Quiz</a> \
  61. <div id=awq_settingsPanel class=awq_settingsP>\
  62. <form> \
  63. <br> \
  64. Debug: <input type=checkbox name=debug id=awq_debug></input>\
  65. </form>\
  66. <button class=awq_style>Hide</button>\
  67. <button class=awq_style>Yep</button>\
  68. </div>\
  69. ");
  70.  
  71.  
  72. $(".navbar-nav:first").append(settings);
  73. $("#awq_settings").addClass("awq_settings");
  74. $("#awq_settingsPanel").hide();
  75. setEventSettings();
  76. loadSettings();
  77. }
  78.  
  79. function loadSettings()
  80. {
  81. var vals = [];
  82. for (var i = 0; i < GM_listValues().length; i++)
  83. {
  84. vals[i] = GM_listValues()[i];
  85. }
  86.  
  87. if (vals.length === 0)
  88. {
  89. GM_setValue("awq_debug", false);
  90. debug = false;
  91. $("#awq_debug").prop("checked", false);
  92. //console.log("debug: " + debug);
  93. }
  94.  
  95. //console.log(vals);
  96.  
  97. for (var i = 0; i < vals.length; i++)
  98. {
  99. if (vals[i] === "awq_debug")
  100. {
  101. debug = GM_getValue("awq_debug");
  102. if (debug)
  103. {
  104. $("#awq_debug").prop("checked", debug);
  105. } else
  106. {
  107. $("#awq_debug").prop("checked", debug);
  108. }
  109. } else
  110. {
  111. //GM_setValue("awq_debug", false);
  112. //debug = false;
  113. //$("#awq_debug").prop("checked", false);
  114. //console.log("debug: " + debug);
  115. }
  116. }
  117.  
  118. if (debug)
  119. {
  120. for (var i = 0; i < vals.length; i++)
  121. {
  122. console.log(vals[i] + " val:" + GM_getValue(vals[i]));
  123. }
  124. }
  125. }
  126.  
  127. function setEventSettings()
  128. {
  129. $("#awq_settings").click(function ()
  130. {
  131. $("#awq_settingsPanel").toggle();
  132. });
  133.  
  134. $("#awq_debug").change(function ()
  135. {
  136. GM_setValue("awq_debug", $(this).prop("checked"));
  137. debug = $(this).prop("checked");
  138. alert("Settings has been changed. Please reload the page.");
  139. });
  140. }
  141.  
  142. function findIndexes(searchStr, str, caseSensitive)
  143. {
  144. var searchStrLen = searchStr.length;
  145. if (searchStrLen == 0) {
  146. return [];
  147. }
  148. var startIndex = 0, index, indices = [];
  149. if (!caseSensitive) {
  150. str = str.toLowerCase();
  151. searchStr = searchStr.toLowerCase();
  152. }
  153. while ((index = str.indexOf(searchStr, startIndex)) > -1) {
  154. indices.push(index);
  155. startIndex = index + searchStrLen;
  156. }
  157. return indices;
  158. }
  159.  
  160. //css styles adds
  161. function cssAdd()
  162. {
  163. $("head").append($("<style type=text/css></style>").text("button.awq_btn { \
  164. \
  165. }"));
  166.  
  167. $("head").append($("<style type=text/css></style>").text("a.awq_settings { \
  168. cursor: pointer;\
  169. }"));
  170.  
  171. $("head").append($("<style type=text/css></style>").text("div.awq_settingsP { \
  172. position:absolute; width:300px; background-color: #fff; border-color: #eee!important; border-radius: .3rem; border: 2px solid transparent; z-index: 150;\
  173. }"));
  174.  
  175. $("head").append($("<style type=text/css></style>").text("button.awq_style { \
  176. cursor: pointer; color: #fff; background-color: #0275d8; border-color: #0275d8; padding: .75rem 1.5rem; font-size: 1rem; border-radius: .3rem; border: 1px solid transparent; max-width:200px; margin:5px;\
  177. }"));
  178.  
  179. $("head").append($("<style type=text/css></style>").text("button.awq_style:hover { \
  180. cursor: pointer; color: #fff; background-color: #025aa5; border-color: #01549b; padding: .75rem 1.5rem; font-size: 1rem; border-radius: .3rem; border: 1px solid transparent;\
  181. }"));
  182.  
  183. $("head").append($("<style type=text/css></style>").text("div.awq_rstyle { \
  184. width:100%; margin-top:30px; z-index: 100;\
  185. }"));
  186.  
  187. $("head").append($("<style type=text/css></style>").text("button.awq_true { \
  188. background-color: #75d802; border-color: #75d802;\
  189. }"));
  190.  
  191. $("head").append($("<style type=text/css></style>").text("button.awq_true:hover { \
  192. background-color: #5aa502; border-color: #5aa502;\
  193. }"));
  194.  
  195. $("head").append($("<style type=text/css></style>").text("button.awq_false { \
  196. background-color: #d80275; border-color: #d80275;\
  197. }"));
  198.  
  199. $("head").append($("<style type=text/css></style>").text("button.awq_false:hover { \
  200. background-color: #a5025a; border-color: #a5025a;\
  201. }"));
  202. }
  203.  
  204. $(document).ready(function () {
  205.  
  206. // Append some text to the element with id someText using the jQuery library.
  207. //$("#studynow").append(" more text...................");
  208.  
  209. $("#studynow").click(function () {
  210. setTimeout(function ()
  211. {
  212. setUI();
  213. searchFor = searchQuestion();
  214. if (debug)
  215. {
  216. console.log("searchFor:" + searchFor);
  217. }
  218. getTrueAnswer(searchFor);
  219. if (debug) {
  220. console.log('Study Click');
  221. }
  222. }, 1500);
  223. });
  224.  
  225. function setUI()
  226. {
  227. const buttonP = $("<button id=awq_quiz class=btn style=margin-left:4px></button>").text("Quiz");
  228. const button = $("<div class=awq_rstyle></div>").html("<button class=awq_btn></button><button class=awq_btn></button><button class=awq_btn></button><button class=awq_btn></button><button class=awq_btn></button><button class=awq_btn></button><button class=awq_btn></button><button class=awq_btn></button>");
  229.  
  230. $(".pt-1").before("<br>");
  231. $(".pt-1").before(button);
  232.  
  233. $("#leftStudyMenu").after(buttonP);
  234.  
  235. settingsEvents();
  236.  
  237. $("#awq_quiz").addClass("btn-secondary");
  238. $(".awq_btn").addClass("awq_style");
  239. $(".awq_rstyle").hide();
  240. }
  241.  
  242. function settingsEvents()
  243. {
  244.  
  245. $("#awq_quiz").click(function () {
  246. $(".awq_rstyle").toggle();
  247. });
  248.  
  249. $("#ansbuta").click(function ()
  250. {
  251. setTimeout(function ()
  252. {
  253. if (debug)
  254. {
  255. console.log("Button check");
  256. }
  257. $("#ease1").click(function ()
  258. {
  259. otherEvent();
  260. });
  261. $("#ease2").click(function ()
  262. {
  263. otherEvent();
  264. });
  265. $("#ease3").click(function ()
  266. {
  267. otherEvent();
  268. });
  269. $("#ease4").click(function ()
  270. {
  271. otherEvent();
  272. });
  273. }, 500);
  274. });
  275.  
  276. $(".awq_btn").click(function ()
  277. {
  278. if (debug)
  279. {
  280. console.log("html:" + $(this).html());
  281. console.log("true:" + trueAnswer);
  282. }
  283.  
  284. if (trueAnswer == $(this).html())
  285. {
  286. $(this).addClass("awq_true");
  287. } else
  288. {
  289. $(this).addClass("awq_false");
  290. }
  291. });
  292. }
  293.  
  294. function escapeRegExp(string)
  295. {
  296. return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
  297. }
  298.  
  299. function searchQuestion()
  300. {
  301. if (debug)
  302. {
  303. console.log("span: ");
  304. console.log($("awq_question").has("span"));
  305. }
  306. if ($("awq_question").has("span").length >= 1)
  307. {
  308. var contentText = $("awq_question").contents().filter(function ()
  309. {
  310. return this.nodeType == 3;
  311. });
  312.  
  313. var contentSpan = $("awq_question").contents().filter(function ()
  314. {
  315. return this.nodeType == 1;
  316. });
  317.  
  318. if (debug)
  319. {
  320. console.log(contentText);
  321. console.log(contentSpan);
  322. }
  323.  
  324. rubyVal = "";
  325.  
  326.  
  327. //This is if first goes hiragana/katakana
  328. if (contentText[0].nodeValue != "")
  329. {
  330. rubyVal = $.trim(contentText[0].nodeValue);
  331. rubyVal += "<ruby><rb>";
  332.  
  333. rubyVal += $.trim($(contentSpan[0]).contents().filter(function ()
  334. {
  335. return this.nodeType == 3;
  336. })[0].nodeValue) + "</rb><rt>";
  337.  
  338. rubyVal += $(contentSpan[0]).contents()[0].innerHTML + "</rt></ruby>";
  339.  
  340. //After kanji goes hiragana/katakana if not return
  341. if (contentText[1] != null)
  342. {
  343. rubyVal += $.trim(contentText[1].nodeValue);
  344. if (contentSpan[1] != null)
  345. {
  346. rubyVal += "<ruby><rb>";
  347. rubyVal += $.trim($(contentSpan[1]).contents().filter(function ()
  348. {
  349. return this.nodeType == 3;
  350. })[0].nodeValue) + "</rb><rt>";
  351.  
  352. rubyVal += $(contentSpan[1]).contents()[0].innerHTML + "</rt></ruby>";
  353.  
  354. //After kanji goes hiragana/katakana if not return
  355. if (contentText[2] != null)
  356. {
  357. rubyVal += $.trim(contentText[2].nodeValue);
  358. if (contentSpan[2] != null)
  359. {
  360. //TODO THIRD
  361. } else
  362. {
  363. if (debug)
  364. {
  365. console.log("Here actua this: " + rubyVal);
  366. }
  367. return rubyVal;
  368. }
  369. } else
  370. {
  371. if (debug)
  372. {
  373. console.log("Here actua this: " + rubyVal);
  374. }
  375. return rubyVal;
  376. }
  377. } else
  378. {
  379. if (debug)
  380. {
  381. console.log("Here actua this: " + rubyVal);
  382. }
  383. return rubyVal;
  384. }
  385. } else
  386. {
  387. if (debug)
  388. {
  389. console.log("Here actua this: " + rubyVal);
  390. }
  391. return rubyVal;
  392. }
  393.  
  394. if (debug)
  395. {
  396. console.log("value first:" + contentText[0].nodeValue);
  397. console.log(contentSpan);
  398. console.log(contentSpan[0].innerHTML);
  399. }
  400. }
  401.  
  402. if (debug)
  403. {
  404. console.log(contentText);
  405. console.log("IT DOES");
  406. console.log($("awq_question").contents());
  407. //rubyVal = $("awq_question").contents().filter(function ()
  408. //{
  409. // return this.nodeType == 3;
  410. //})[0].nodeValue;
  411. console.log("Here actua this: " + rubyVal);
  412. }
  413. } else
  414. {
  415. return $.trim($("awq_question").html());
  416. }
  417. }
  418.  
  419. function getTrueAnswer(sFor)
  420. {
  421. var regex = '(^|\\s|\\b|(\\>))';
  422. regex += escapeRegExp(sFor);
  423. regex += '($|\\s|\\b|(\\<))';
  424.  
  425. if (debug)
  426. {
  427. console.log(regex);
  428. }
  429.  
  430. for (var i = 0; i < tempStrings.length; i++) {
  431. //console.log('sFor =' + sFor + " leng " + sFor.length + " debug : " + new RegExp(regex, "g").test(tempStrings[i]));
  432. //contains = tempStrings[i].matches(".*\\bram\\b.*");
  433. if (new RegExp(regex, "g").test(tempStrings[i]))
  434. {
  435. const str = tempStrings[i].toString();
  436. trueAnswer = $.trim(str.slice(str.indexOf(inBegAnswer) + 12, str.indexOf(inEndAnswer)));
  437. trueId = i;
  438. if (debug)
  439. {
  440. //console.log(tempStrings[i - 1]);
  441. console.log(str);
  442. //console.log(tempStrings[i + 1]);
  443. console.log("True answer : " + trueAnswer + " id trueAnsw = " + trueId);
  444. }
  445. getFalseAnswers(trueId);
  446. break;
  447. }
  448. }
  449. }
  450.  
  451. function getFalseAnswers(trueId) {
  452. tempArr.length = 0;
  453. for (var i = 0; i < 7; i++) {
  454. id = get_rand(tempStrings);
  455. if (id != trueId) {
  456. if (debug) {
  457. console.log(tempStrings[id]);
  458. }
  459. const str = tempStrings[id].toString();
  460. falseAnswers[i] = str.slice(str.indexOf(inBegAnswer) + 12, str.indexOf(inEndAnswer));
  461. if (debug) {
  462. console.log("***False answer " + i + " : " + falseAnswers[i] + " id: " + id);
  463. //console.log("inBegAnswer: " + str.indexOf(inBegAnswer) + " : " + str.indexOf(inEndAnswer) + " inEndAnswer");
  464. }
  465. } else {
  466. id = get_rand(tempStrings);
  467. i--;
  468. }
  469. }
  470. ramdomButton();
  471. }
  472.  
  473. function otherEvent()
  474. {
  475. if (debug) {
  476. console.log("Button click");
  477. console.log("---------------");
  478. }
  479. searchFor = "";
  480. //searchFor = $("awq_question").html();
  481. searchFor = searchQuestion();
  482. if (debug) {
  483. console.log("searchFor:" + searchFor);
  484. console.log($("awq").text().length);
  485. }
  486. $(".awq_rstyle").hide();
  487. if (searchFor == "") {
  488. setTimeout(function () {
  489. if ($("awq").text().length === 0) {
  490. setTimeout(function () {
  491. //searchFor = $("awq_question").html();
  492. searchFor = searchQuestion();
  493. if (debug) {
  494. console.log("searchFor:::" + searchFor);
  495. }
  496. getTrueAnswer(searchFor);
  497. }, 3000);
  498. } else {
  499. //searchFor = $("awq_question").html();
  500. searchFor = searchQuestion();
  501. if (debug) {
  502. console.log("searchFor::" + searchFor);
  503. }
  504. getTrueAnswer(searchFor);
  505. }
  506. }, 1000);
  507. } else {
  508. getTrueAnswer(searchFor);
  509. }
  510. }
  511.  
  512. //random functions
  513. function in_array(array, el) {
  514. for (var i = 0 ; i < array.length; i++)
  515. if (array[i] == el) return true;
  516. return false;
  517. }
  518.  
  519. function get_rand(array) {
  520. var rand = Math.floor(Math.random() * array.length);
  521. if (!in_array(tempArr, rand)) {
  522. tempArr.push(rand);
  523. return rand;
  524. }
  525. return get_rand(array);
  526. }
  527. //end of random functions
  528.  
  529. function ramdomButton()
  530. {
  531. buttons.length = 0;
  532. tempArr.length = 0;
  533. var allAnswers = [];
  534. allAnswers[0] = trueAnswer;
  535. for (var i = 1; i <= falseAnswers.length; i++) {
  536. allAnswers[i] = falseAnswers[i - 1];
  537. }
  538. if (debug) {
  539. console.log("False answers :");
  540. console.log(falseAnswers);
  541. console.log("ALL answers :");
  542. console.log(allAnswers);
  543. }
  544. for (var i = 0; i < allAnswers.length; i++) {
  545. buttons[i] = $.trim(allAnswers[get_rand(allAnswers)]);
  546. }
  547. if (debug) {
  548. console.log("Random order :) = " + buttons);
  549. // console.log($(".awq_LeftSide").html());
  550. }
  551. uiButtons();
  552. }
  553.  
  554. function uiButtons()
  555. {
  556. const sel = document.querySelectorAll("button.awq_btn");
  557. if (debug)
  558. {
  559. console.log("*HERE UI BUTTONS :");
  560. }
  561.  
  562. for (var i = 0; i < buttons.length; i++)
  563. {
  564. //Delete arttribute
  565. if ($(sel[i]).attr("title"))
  566. {
  567. $(sel[i]).removeAttr("title");
  568. }
  569.  
  570. if (buttons[i].length <= 40 || buttons[i].includes("</ruby>"))
  571. {
  572. $(sel[i]).html(buttons[i]);
  573. } else
  574. {
  575. $(sel[i]).html(buttons[i].slice(0, 40) + "...");
  576. $(sel[i]).attr("title", buttons[i]);
  577. }
  578. if (debug)
  579. {
  580. //console.log(sel[i]);
  581. console.log(buttons[i] + " Length: " + buttons[i].length);
  582. console.log(buttons[i].includes("</ruby>"));
  583. }
  584. }
  585.  
  586. checkPresedButtons();
  587. }
  588.  
  589. function checkPresedButtons()
  590. {
  591. $(".awq_btn").removeClass("awq_true");
  592. $(".awq_btn").removeClass("awq_false");
  593. }
  594.  
  595. console.log("AnkiWeb Quiz v" + GM_info.script.version + " Initialized");
  596. });
  597.  
  598.  
  599. // ------------
  600. // TODO
  601. // ------------
  602.  
  603. /* TODO STARTS
  604. ✓ 1)Make it only one element of buttons //DONE 0.0.9
  605. 1.1)Increase numbers of buttons to 10-12(optional through settings???)
  606. ✓ 2)Make it limit of length answer and put whole in attribute title //DONE 0.1.0
  607. 3)Make it settings, almost done in 0.1.0
  608. ✓ 3.1)Debug //DONE 0.1.0
  609. 3.2)Add txt file ***RESEARCH NEEDED***
  610. 3.2.1)Choose them
  611. 3.3)Make it always show quiz
  612. ✓ 4)Make it full functionality of Japanese deck, partial done in 0.0.8 //DONE 0.0.9 Happy with that :)
  613. 5)Search question in between tags <awq_question> and </awq_question> not in whole sentence
  614. 6)TODO for loop in finding question
  615. TODO ENDS */