Khan Academy Problem Solver

Here is a Khan Academy Solver!

目前为 2021-12-17 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Khan Academy Problem Solver
  3. // @version 3.0
  4. // @description Here is a Khan Academy Solver!
  5. // @author Logzilla6
  6. // @match https://www.khanacademy.org/*
  7. // @grant none
  8. // @namespace https://greasyfork.org/users/783447
  9. // ==/UserScript==
  10. (function () {
  11. let overlayHTML = ` <link rel="preconnect" href="https://fonts.googleapis.com">
  12. <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  13. <link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
  14. <div id="box">
  15. <button class="ou" id="accordian">Toggle</button>
  16. <div class="ou" id="box2">
  17. <p class="pdark" id="pdark"> KhanHack </p>
  18. <section><label>Answer: [<label id="ans1">...</label>]</label></section>
  19. <section><label>Next And Last Answer: [<label id="ans2"></label>]</label></section>
  20. <section><label>&nbsp;</label></section>
  21. <section><label id="ans3text">Dropdown 1: [<label id="ans3">...</label>]</label></section>
  22. <section><label id="ans4text">Dropdown 2: [<label id="ans4">...</label>]</label></section>
  23. <section><label id="ans5text">Dropdown 3: [<label id="ans5">...</label>]</label></section>
  24. <section><label>&nbsp;</label></section>
  25. <section><label>M also toggles Menu</label></section>
  26. </div>
  27. </div>
  28. <style>
  29.  
  30. #box {
  31. z-index: 1090;
  32. position: fixed;
  33. top: 0;
  34. right: 0;}
  35. #box2 {
  36. padding: 15px;
  37. margin-bottom: 5px;
  38. display: none;
  39. border-radius: 25px;};
  40. section {
  41. display: flex;
  42. justify-content: space-between;margin:5px;}
  43. .ou {
  44. background-color: #072357;
  45. letter-spacing: 2px;
  46. font-weight: none;
  47. font-size: 11px;
  48. font-family: 'Roboto', sans-serif;
  49. color:white;}
  50. .pdark {
  51. text-align: center;
  52. border-bottom:2px solid white;}
  53. #accordian {
  54. width: 100%;
  55. border: 0;
  56. cursor: pointer;
  57. border-radius: 25px;}
  58. label { font-weight: bold;}
  59. </style>
  60. `
  61. function get(x) { return document.getElementById(x); }
  62. let overlay = document.createElement("div");
  63. overlay.innerHTML = overlayHTML;
  64. document.body.appendChild(overlay);
  65. let acc = get("accordian"),
  66. darkToggle = get("darkToggle")
  67. acc.onclick = function() {
  68. let panel = get("box2");
  69. if (panel.style.display == "grid") panel.style.display = "none";
  70. else { panel.style.display = "grid"; }
  71. }
  72. document.addEventListener('keydown', (event) => {
  73. if (event.key === 'm') {
  74. let panel = get("box2");
  75. if (panel.style.display == "grid") panel.style.display = "none";
  76. else { panel.style.display = "grid"; }
  77. }
  78. });
  79.  
  80. 'use strict';
  81. window.loaded = false;
  82. class Answer {
  83. constructor(answer, type) {
  84. this.body = answer;
  85. this.type = type;
  86. }
  87. get isMultiChoice() {
  88. return this.type == "multiple_choice";
  89. }
  90. get isFreeResponse() {
  91. return this.type == "free_response";
  92. }
  93. get isExpression() {
  94. return this.type == "expression";
  95. }
  96. get isDropdown() {
  97. return this.type == "dropdown";
  98. }
  99. log() {
  100. const answer = this.body;
  101. const style = "color: coral; -webkit-text-stroke: .5px black; font-size:24px; font-weight:bold;";
  102. answer.map(ans => {
  103. if (typeof ans == "string") {
  104. if (ans.includes("web+graphie")) {
  105. this.body[this.body.indexOf(ans)] = "";
  106. this.printImage(ans);
  107. } else {
  108. answer[answer.indexOf(ans)] = ans.replaceAll("$", "");
  109. }
  110. }
  111. });
  112. const text = answer.join("\n");
  113. if (text) {
  114. console.log(`${text.trim()}`, style);
  115. }
  116. }
  117. printImage(ans) {
  118. const url = ans.replace("![](web+graphie", "https").replace(")", ".svg");
  119. const image = new Image();
  120. image.src = url;
  121. image.onload = () => {
  122. const imageStyle = [
  123. 'font-size: 1px;',
  124. 'line-height: ', this.height % 2, 'px;',
  125. 'padding: ', this.height * .5, 'px ', this.width * .5, 'px;',
  126. 'background-size: ', this.width, 'px ', this.height, 'px;',
  127. 'background: url(', url, ');'
  128. ].join(' ');
  129. console.log('', imageStyle);
  130. };
  131. }
  132. }
  133. const originalFetch = window.fetch;
  134. window.fetch = function () {
  135. return originalFetch.apply(this, arguments).then((res) => {
  136. if (res.url.includes("/getAssessmentItem")) {
  137. const clone = res.clone();
  138. clone.json().then(json => {
  139. let item, question;
  140. try {
  141. item = json.data.assessmentItem.item.itemData;
  142. question = JSON.parse(item).question;
  143. } catch {
  144. let errorIteration = () => { return localStorage.getItem("error_iter") || 0; }
  145. localStorage.setItem("error_iter", errorIteration() + 1);
  146. if (errorIteration() < 4) {
  147. return location.reload();
  148. } else {
  149. return alert("An error occurred");
  150. }
  151. }
  152. if (!question) return;
  153. Object.keys(question.widgets).map(widgetName => {
  154. switch (widgetName.split(" ")[0]) {
  155. case "numeric-input":
  156. return freeResponseAnswerFrom(question).log();
  157. case "radio":
  158. return multipleChoiceAnswerFrom(question).log();
  159. case "expression":
  160. return expressionAnswerFrom(question).log();
  161. case "dropdown":
  162. return dropdownAnswerFrom(question).log();
  163. }
  164. });
  165. });
  166. }
  167. return res;
  168. })
  169. }
  170. function freeResponseAnswerFrom(question) {
  171. const answer = Object.values(question.widgets).map((widget) => {
  172. if (widget.options?.answers) {
  173. return widget.options.answers.map(answer => {
  174. if (answer.status == "correct") {
  175. //alert('freeresponse')
  176. var ans1 = document.getElementById('ans1').innerHTML
  177. var ans2 = document.getElementById('ans2').innerHTML
  178. document.getElementById('ans2').innerHTML = document.getElementById('ans2').innerHTML.replace("![](web+graphie://cdn.kastatic.org/ka-perseus-graphie/", "")
  179. document.getElementById('ans2').innerHTML = document.getElementById('ans2').innerHTML.replace("$", "")
  180. document.getElementById('ans2').innerHTML = (answer.value)
  181. document.getElementById('ans1').innerHTML = (ans2)
  182. document.getElementById('ans1').innerHTML = document.getElementById('ans1').innerHTML.replace("![](web+graphie://cdn.kastatic.org/ka-perseus-graphie/", "")
  183. document.getElementById('ans1').innerHTML = document.getElementById('ans1').innerHTML.replace("$", "")
  184. }
  185. });
  186. }
  187. }).flat().filter((val) => { return val !== undefined; });
  188. return new Answer(answer, "free_response");
  189. }
  190. function multipleChoiceAnswerFrom(question) {
  191. const answer = Object.values(question.widgets).map((widget) => {
  192. if (widget.options?.choices) {
  193. return widget.options.choices.map(choice => {
  194. if (choice.correct) {
  195. //alert('multichoice')
  196. var ans1 = document.getElementById('ans1').innerHTML
  197. var ans2 = document.getElementById('ans2').innerHTML
  198. document.getElementById('ans2').innerHTML = document.getElementById('ans2').innerHTML.replace("![](web+graphie://cdn.kastatic.org/ka-perseus-graphie/", "")
  199. document.getElementById('ans2').innerHTML = document.getElementById('ans2').innerHTML.replace("$", "")
  200. document.getElementById('ans2').innerHTML = (choice.content)
  201. document.getElementById('ans1').innerHTML = (ans2)
  202. document.getElementById('ans1').innerHTML = document.getElementById('ans1').innerHTML.replace("![](web+graphie://cdn.kastatic.org/ka-perseus-graphie/", "")
  203. document.getElementById('ans1').innerHTML = document.getElementById('ans1').innerHTML.replace("$", "")
  204. }
  205. });
  206. }
  207. }).flat().filter((val) => { return val !== undefined; });
  208. return new Answer(answer, "multiple_choice");
  209. }
  210. function expressionAnswerFrom(question) {
  211. const answer = Object.values(question.widgets).map((widget) => {
  212. if (widget.options?.answerForms) {
  213. return widget.options.answerForms.map(answer => {
  214. if (Object.values(answer).includes("correct")) {
  215. //alert('expression')
  216. var ans1 = document.getElementById('ans1').innerHTML
  217. var ans2 = document.getElementById('ans2').innerHTML
  218. document.getElementById('ans2').innerHTML = document.getElementById('ans2').innerHTML.replace("![](web+graphie://cdn.kastatic.org/ka-perseus-graphie/", "")
  219. document.getElementById('ans2').innerHTML = document.getElementById('ans2').innerHTML.replace("$", "")
  220. document.getElementById('ans2').innerHTML = (answer.value)
  221. document.getElementById('ans1').innerHTML = (ans2)
  222. document.getElementById('ans1').innerHTML = document.getElementById('ans1').innerHTML.replace("![](web+graphie://cdn.kastatic.org/ka-perseus-graphie/", "")
  223. document.getElementById('ans1').innerHTML = document.getElementById('ans1').innerHTML.replace("$", "")
  224. }
  225. });
  226. }
  227. }).flat();
  228. return new Answer(answer, "expression");
  229. }
  230. function dropdownAnswerFrom(question) {
  231. const answer = Object.values(question.widgets).map((widget) => {
  232. if (widget.options?.choices) {
  233. return widget.options.choices.map(choice => {
  234. if (choice.correct) {
  235. //alert('dropdown')
  236. var ans1 = document.getElementById('ans1').innerHTML
  237. var ans2 = document.getElementById('ans2').innerHTML
  238. var ans3 = document.getElementById('ans3').innerHTML
  239. var ans4 = document.getElementById('ans4').innerHTML
  240. var ans5 = document.getElementById('ans5').innerHTML
  241. document.getElementById('ans2').innerHTML = document.getElementById('ans2').innerHTML.replace("![](web+graphie://cdn.kastatic.org/ka-perseus-graphie/", "")
  242. document.getElementById('ans2').innerHTML = document.getElementById('ans2').innerHTML.replace("$", "")
  243. document.getElementById('ans2').innerHTML = (choice.content)
  244. document.getElementById('ans1').innerHTML = (ans2)
  245. document.getElementById('ans5').innerHTML = (choice.content)
  246. document.getElementById('ans4').innerHTML = (ans5)
  247. document.getElementById('ans3').innerHTML = (ans4)
  248. document.getElementById('ans1').innerHTML = document.getElementById('ans1').innerHTML.replace("![](web+graphie://cdn.kastatic.org/ka-perseus-graphie/", "")
  249. document.getElementById('ans1').innerHTML = document.getElementById('ans1').innerHTML.replace("$", "")
  250. }
  251. });
  252. }
  253. }).flat();
  254. return new Answer(answer, "dropdown");
  255. }
  256. })();