AnkiWeb Quiz

Shows quiz on ankiweb

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

  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.2
  10. // @grant GM_getResourceText
  11. // @grant GM_listValues
  12. // @grant GM_deleteValue
  13. // @grant GM_getValue
  14. // @grant GM_setValue
  15. // @resource ankiDeck PUT_HERE_YOUR_DECK.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. if ($(this).attr("title"))
  281. {
  282. console.log("html:" + $(this).attr("title"));
  283. console.log("true:" + trueAnswer);
  284. } else
  285. {
  286. console.log("html:" + $(this).html);
  287. console.log("true:" + trueAnswer);
  288. }
  289. }
  290.  
  291. if ($(this).attr("title"))
  292. {
  293. if (trueAnswer == $(this).attr("title"))
  294. {
  295. $(this).addClass("awq_true");
  296. } else
  297. {
  298. $(this).addClass("awq_false");
  299. }
  300. } else
  301. {
  302. if (trueAnswer == $(this).html())
  303. {
  304. $(this).addClass("awq_true");
  305. } else
  306. {
  307. $(this).addClass("awq_false");
  308. }
  309. }
  310. });
  311. }
  312.  
  313. function escapeRegExp(string)
  314. {
  315. return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
  316. }
  317.  
  318. function searchQuestion()
  319. {
  320. if (debug)
  321. {
  322. console.log("span: ");
  323. console.log($("awq_question").has("span"));
  324. }
  325. if ($("awq_question").has("span").length >= 1)
  326. {
  327. var contentText = $("awq_question").contents().filter(function ()
  328. {
  329. return this.nodeType == 3;
  330. });
  331.  
  332. var contentSpan = $("awq_question").contents().filter(function ()
  333. {
  334. return this.nodeType == 1;
  335. });
  336.  
  337. if (debug)
  338. {
  339. console.log(contentText);
  340. console.log(contentSpan);
  341. }
  342.  
  343. rubyVal = "";
  344.  
  345.  
  346. //This is if first goes hiragana/katakana
  347. if (contentText[0].nodeValue != "")
  348. {
  349. rubyVal = $.trim(contentText[0].nodeValue);
  350. rubyVal += "<ruby><rb>";
  351.  
  352. rubyVal += $.trim($(contentSpan[0]).contents().filter(function ()
  353. {
  354. return this.nodeType == 3;
  355. })[0].nodeValue) + "</rb><rt>";
  356.  
  357. rubyVal += $(contentSpan[0]).contents()[0].innerHTML + "</rt></ruby>";
  358.  
  359. //After kanji goes hiragana/katakana if not return
  360. if (contentText[1] != null)
  361. {
  362. rubyVal += $.trim(contentText[1].nodeValue);
  363. if (contentSpan[1] != null)
  364. {
  365. rubyVal += "<ruby><rb>";
  366. rubyVal += $.trim($(contentSpan[1]).contents().filter(function ()
  367. {
  368. return this.nodeType == 3;
  369. })[0].nodeValue) + "</rb><rt>";
  370.  
  371. rubyVal += $(contentSpan[1]).contents()[0].innerHTML + "</rt></ruby>";
  372.  
  373. //After kanji goes hiragana/katakana if not return
  374. if (contentText[2] != null)
  375. {
  376. rubyVal += $.trim(contentText[2].nodeValue);
  377. if (contentSpan[2] != null)
  378. {
  379. //TODO THIRD
  380. } else
  381. {
  382. if (debug)
  383. {
  384. console.log("Here actua this: " + rubyVal);
  385. }
  386. return rubyVal;
  387. }
  388. } else
  389. {
  390. if (debug)
  391. {
  392. console.log("Here actua this: " + rubyVal);
  393. }
  394. return rubyVal;
  395. }
  396. } else
  397. {
  398. if (debug)
  399. {
  400. console.log("Here actua this: " + rubyVal);
  401. }
  402. return rubyVal;
  403. }
  404. } else
  405. {
  406. if (debug)
  407. {
  408. console.log("Here actua this: " + rubyVal);
  409. }
  410. return rubyVal;
  411. }
  412.  
  413. if (debug)
  414. {
  415. console.log("value first:" + contentText[0].nodeValue);
  416. console.log(contentSpan);
  417. console.log(contentSpan[0].innerHTML);
  418. }
  419. }
  420.  
  421. if (debug)
  422. {
  423. console.log(contentText);
  424. console.log("IT DOES");
  425. console.log($("awq_question").contents());
  426. //rubyVal = $("awq_question").contents().filter(function ()
  427. //{
  428. // return this.nodeType == 3;
  429. //})[0].nodeValue;
  430. console.log("Here actua this: " + rubyVal);
  431. }
  432. } else
  433. {
  434. return $.trim($("awq_question").html());
  435. }
  436. }
  437.  
  438. function getTrueAnswer(sFor)
  439. {
  440. var regex = '(^|\\s|\\b|(n\\>))';
  441. var tempQuestion;
  442. var strQ;
  443. regex += escapeRegExp(sFor);
  444. regex += '($|\\s|\\b|(\\<\\/a))';
  445.  
  446. if (debug)
  447. {
  448. console.log(regex);
  449. }
  450.  
  451. for (var i = 0; i < tempStrings.length; i++) {
  452. //console.log('sFor =' + sFor + " leng " + sFor.length + " debug : " + new RegExp(regex, "g").test(tempStrings[i]));
  453. //contains = tempStrings[i].matches(".*\\bram\\b.*");
  454. //tempQuestion = '';
  455. //strQ = '';
  456. //strQ = tempStrings[i].toString();
  457. //tempQuestion = $.trim(str.slice(str.indexOf("<awq_question>") + 14, str.indexOf("</awq_question>")));
  458. //console.log(tempQuestion);
  459. if (new RegExp(regex, "g").test(tempStrings[i]))
  460. {
  461. const str = tempStrings[i].toString();
  462. trueAnswer = $.trim(str.slice(str.indexOf(inBegAnswer) + 12, str.indexOf(inEndAnswer)));
  463. trueId = i;
  464. if (debug)
  465. {
  466. //console.log(tempStrings[i - 1]);
  467. console.log(str);
  468. console.log(tempQuestion);
  469. //console.log(tempStrings[i + 1]);
  470. console.log("True answer : " + trueAnswer + " id trueAnsw = " + trueId);
  471. }
  472. getFalseAnswers(trueId);
  473. break;
  474. }
  475. }
  476. }
  477.  
  478. function getFalseAnswers(trueId) {
  479. tempArr.length = 0;
  480. for (var i = 0; i < 7; i++) {
  481. id = get_rand(tempStrings);
  482. if (id != trueId) {
  483. if (debug) {
  484. console.log(tempStrings[id]);
  485. }
  486. const str = tempStrings[id].toString();
  487. falseAnswers[i] = str.slice(str.indexOf(inBegAnswer) + 12, str.indexOf(inEndAnswer));
  488. if (debug) {
  489. console.log("***False answer " + i + " : " + falseAnswers[i] + " id: " + id);
  490. //console.log("inBegAnswer: " + str.indexOf(inBegAnswer) + " : " + str.indexOf(inEndAnswer) + " inEndAnswer");
  491. }
  492. } else {
  493. id = get_rand(tempStrings);
  494. i--;
  495. }
  496. }
  497. ramdomButton();
  498. }
  499.  
  500. function otherEvent()
  501. {
  502. if (debug) {
  503. console.log("Button click");
  504. console.log("---------------");
  505. }
  506. searchFor = "";
  507. //searchFor = $("awq_question").html();
  508. searchFor = searchQuestion();
  509. if (debug) {
  510. console.log("searchFor:" + searchFor);
  511. console.log($("awq").text().length);
  512. }
  513. $(".awq_rstyle").hide();
  514. if (searchFor == "") {
  515. setTimeout(function () {
  516. if ($("awq").text().length === 0) {
  517. setTimeout(function () {
  518. //searchFor = $("awq_question").html();
  519. searchFor = searchQuestion();
  520. if (debug) {
  521. console.log("searchFor:::" + searchFor);
  522. }
  523. getTrueAnswer(searchFor);
  524. }, 3000);
  525. } else {
  526. //searchFor = $("awq_question").html();
  527. searchFor = searchQuestion();
  528. if (debug) {
  529. console.log("searchFor::" + searchFor);
  530. }
  531. getTrueAnswer(searchFor);
  532. }
  533. }, 1000);
  534. } else {
  535. getTrueAnswer(searchFor);
  536. }
  537. }
  538.  
  539. //random functions
  540. function in_array(array, el) {
  541. for (var i = 0 ; i < array.length; i++)
  542. if (array[i] == el) return true;
  543. return false;
  544. }
  545.  
  546. function get_rand(array) {
  547. var rand = Math.floor(Math.random() * array.length);
  548. if (!in_array(tempArr, rand)) {
  549. tempArr.push(rand);
  550. return rand;
  551. }
  552. return get_rand(array);
  553. }
  554. //end of random functions
  555.  
  556. function ramdomButton()
  557. {
  558. buttons.length = 0;
  559. tempArr.length = 0;
  560. var allAnswers = [];
  561. allAnswers[0] = trueAnswer;
  562. for (var i = 1; i <= falseAnswers.length; i++) {
  563. allAnswers[i] = falseAnswers[i - 1];
  564. }
  565. if (debug) {
  566. console.log("False answers :");
  567. console.log(falseAnswers);
  568. console.log("ALL answers :");
  569. console.log(allAnswers);
  570. }
  571. for (var i = 0; i < allAnswers.length; i++) {
  572. buttons[i] = $.trim(allAnswers[get_rand(allAnswers)]);
  573. }
  574. if (debug) {
  575. console.log("Random order :) = " + buttons);
  576. // console.log($(".awq_LeftSide").html());
  577. }
  578. uiButtons();
  579. }
  580.  
  581. function uiButtons()
  582. {
  583. const sel = document.querySelectorAll("button.awq_btn");
  584. if (debug)
  585. {
  586. console.log("*HERE UI BUTTONS :");
  587. }
  588.  
  589. for (var i = 0; i < buttons.length; i++)
  590. {
  591. //Delete arttribute
  592. if ($(sel[i]).attr("title"))
  593. {
  594. $(sel[i]).removeAttr("title");
  595. }
  596.  
  597. if (buttons[i].length <= 40 || buttons[i].includes("</ruby>"))
  598. {
  599. $(sel[i]).html(buttons[i]);
  600. } else
  601. {
  602. $(sel[i]).html(buttons[i].slice(0, 40) + "...");
  603. $(sel[i]).attr("title", buttons[i]);
  604. }
  605. if (debug)
  606. {
  607. //console.log(sel[i]);
  608. console.log(buttons[i] + " Length: " + buttons[i].length);
  609. console.log(buttons[i].includes("</ruby>"));
  610. }
  611. }
  612.  
  613. checkPresedButtons();
  614. }
  615.  
  616. function checkPresedButtons()
  617. {
  618. $(".awq_btn").removeClass("awq_true");
  619. $(".awq_btn").removeClass("awq_false");
  620. }
  621.  
  622. console.log("AnkiWeb Quiz v" + GM_info.script.version + " Initialized");
  623. });
  624.  
  625.  
  626. // ------------
  627. // TODO
  628. // ------------
  629.  
  630. /* TODO STARTS
  631. ✓ 1)Make it only one element of buttons //DONE 0.0.9
  632. 1.1)Increase numbers of buttons to 10-12(optional through settings???)
  633. ✓ 2)Make it limit of length answer and put whole in attribute title //DONE 0.1.0
  634. 3)Make it settings, almost done in 0.1.0
  635. ✓ 3.1)Debug //DONE 0.1.0
  636. 3.2)Add txt file ***RESEARCH NEEDED***
  637. 3.2.1)Choose them
  638. 3.3)Make it always show quiz
  639. ✓ 4)Make it full functionality of Japanese deck, partial done in 0.0.8 //DONE 0.0.9 Happy with that :)
  640. 5)Search question in between tags <awq_question> and </awq_question> not in whole sentence, almost done in 0.1.2
  641. 6)TODO for loop in finding question
  642. TODO ENDS */