Khan Academy Problem Solver

Here is a Khan Solver!

当前为 2021-06-15 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Khan Academy Problem Solver
  3. // @version 1.2
  4. // @description Here is a Khan Solver!
  5. // @author Logzilla6
  6. // @match https://www.khanacademy.org/*
  7. // @grant none
  8. // @namespace https://greasyfork.org/users/783447
  9. // ==/UserScript==
  10.  
  11. (function () {
  12. 'use strict';
  13. window.loaded = false;
  14. alert("Solver Will Say Answers For Problem 1 and 2,"+"\n"+ "then after solving problem 1, Solver Will then give answer to 3, then 4 and so on.");
  15. class Answer {
  16. constructor(answer, type) {
  17. this.body = answer;
  18. this.type = type;
  19. }
  20.  
  21. get isMultiChoice() {
  22. return this.type == "multiple_choice";
  23. }
  24.  
  25. get isFreeResponse() {
  26. return this.type == "free_response";
  27. }
  28.  
  29. get isExpression() {
  30. return this.type == "expression";
  31. }
  32.  
  33. get isDropdown() {
  34. return this.type == "dropdown";
  35. }
  36.  
  37. log() {
  38. const answer = this.body;
  39. const style = "color: coral; -webkit-text-stroke: .5px black; font-size:24px; font-weight:bold;";
  40.  
  41. answer.map(ans => {
  42. if (typeof ans == "string") {
  43. if (ans.includes("web+graphie")) {
  44. this.body[this.body.indexOf(ans)] = "";
  45. this.printImage(ans);
  46. } else {
  47. answer[answer.indexOf(ans)] = ans.replaceAll("$", "");
  48. }
  49. }
  50. });
  51.  
  52. const text = answer.join("\n");
  53. if (text) {
  54. console.log(`${text.trim()}`, style);
  55. }
  56. }
  57.  
  58. printImage(ans) {
  59. const url = ans.replace("![](web+graphie", "https").replace(")", ".svg");
  60. const image = new Image();
  61.  
  62. image.src = url;
  63. image.onload = () => {
  64. const imageStyle = [
  65. 'font-size: 1px;',
  66. 'line-height: ', this.height % 2, 'px;',
  67. 'padding: ', this.height * .5, 'px ', this.width * .5, 'px;',
  68. 'background-size: ', this.width, 'px ', this.height, 'px;',
  69. 'background: url(', url, ');'
  70. ].join(' ');
  71. console.log('', imageStyle);
  72. };
  73. }
  74. }
  75.  
  76. const originalFetch = window.fetch;
  77. window.fetch = function () {
  78. return originalFetch.apply(this, arguments).then((res) => {
  79. if (res.url.includes("/getAssessmentItem")) {
  80. const clone = res.clone();
  81. clone.json().then(json => {
  82. let item, question;
  83.  
  84. try {
  85. item = json.data.assessmentItem.item.itemData;
  86. question = JSON.parse(item).question;
  87. } catch {
  88. let errorIteration = () => { return localStorage.getItem("error_iter") || 0; }
  89. localStorage.setItem("error_iter", errorIteration() + 1);
  90.  
  91. if (errorIteration() < 4) {
  92. return location.reload();
  93. } else {
  94. return alert("%c An error occurred", "color: red; font-weight: bolder; font-size: 20px;");
  95. }
  96. }
  97.  
  98. if (!question) return;
  99.  
  100. Object.keys(question.widgets).map(widgetName => {
  101. switch (widgetName.split(" ")[0]) {
  102. case "numeric-input":
  103. return freeResponseAnswerFrom(question).log();
  104. case "radio":
  105. return multipleChoiceAnswerFrom(question).log();
  106. case "expression":
  107. return expressionAnswerFrom(question).log();
  108. case "dropdown":
  109. return dropdownAnswerFrom(question).log();
  110. }
  111. });
  112. });
  113. }
  114.  
  115. if (!window.loaded) {
  116. console.clear();
  117. console.log("%c Color Picker ", "color: mediumvioletred; -webkit-text-stroke: .5px black; font-size:40px; font-weight:bolder; padding: .2rem;");
  118. console.log("%c Created by Logzilla6", "color: white; -webkit-text-stroke: .5px black; font-size:15px; font-weight:bold;");
  119. window.loaded = true;
  120. }
  121.  
  122. return res;
  123. })
  124. }
  125.  
  126. function freeResponseAnswerFrom(question) {
  127. const answer = Object.values(question.widgets).map((widget) => {
  128. if (widget.options?.answers) {
  129. return widget.options.answers.map(answer => {
  130. if (answer.status == "correct") {
  131. return alert("Answer: If it is really long, just paste the whole thing in!"+"\n"+answer.value);
  132. }
  133. });
  134. }
  135. }).flat().filter((val) => { return val !== undefined; });
  136.  
  137. return new Answer(answer, "free_response");
  138. }
  139.  
  140. function multipleChoiceAnswerFrom(question) {
  141. const answer = Object.values(question.widgets).map((widget) => {
  142. if (widget.options?.choices) {
  143. return widget.options.choices.map(choice => {
  144. if (choice.correct) {
  145. return alert("Answer:"+"\n"+choice.content);
  146. }
  147. });
  148. }
  149. }).flat().filter((val) => { return val !== undefined; });
  150.  
  151. return new Answer(answer, "multiple_choice");
  152. }
  153.  
  154. function expressionAnswerFrom(question) {
  155. const answer = Object.values(question.widgets).map((widget) => {
  156. if (widget.options?.answerForms) {
  157. return widget.options.answerForms.map(answer => {
  158. if (Object.values(answer).includes("correct")) {
  159. return alert("Answer:"+"\n"+answer.value);
  160. }
  161. });
  162. }
  163. }).flat();
  164.  
  165. return new Answer(answer, "expression");
  166. }
  167.  
  168. function dropdownAnswerFrom(question) {
  169. const answer = Object.values(question.widgets).map((widget) => {
  170. if (widget.options?.choices) {
  171. return widget.options.choices.map(choice => {
  172. if (choice.correct) {
  173. return alert("Answer:"+"\n"+choice.content);
  174. }
  175. });
  176. }
  177. }).flat();
  178.  
  179. return new Answer(answer, "dropdown");
  180. }
  181. })();