AnkiWeb Quiz

Shows quiz on ankiweb

当前为 2017-04-21 提交的版本,查看 最新版本

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