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