math-exercises 3.0.124 → 3.0.125

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/lib/exercises/math/calcul/arithmetics/primeNumbers.d.ts +1 -1
  2. package/lib/exercises/math/calcul/arithmetics/primeNumbers.d.ts.map +1 -1
  3. package/lib/exercises/math/calcul/arithmetics/primeNumbers.js +20 -14
  4. package/lib/exercises/math/calcul/fractions/fractionsMix.js +1 -1
  5. package/lib/exercises/math/conversion/volumeConversion.d.ts.map +1 -1
  6. package/lib/exercises/math/conversion/volumeConversion.js +7 -1
  7. package/lib/exercises/math/derivation/derivative/exp/expDerivativeFour.d.ts.map +1 -1
  8. package/lib/exercises/math/derivation/derivative/exp/expDerivativeFour.js +9 -3
  9. package/lib/exercises/math/functions/affines/drawAffineFromLitExp.js +5 -5
  10. package/lib/exercises/math/functions/basics/findZeroesProductQuotient.d.ts.map +1 -1
  11. package/lib/exercises/math/functions/basics/findZeroesProductQuotient.js +29 -2
  12. package/lib/exercises/math/functions/basics/inverseImageFunctionGeogebra.d.ts.map +1 -1
  13. package/lib/exercises/math/functions/basics/inverseImageFunctionGeogebra.js +72 -61
  14. package/lib/exercises/math/functions/trinoms/roots/rootsFromDevForm.d.ts.map +1 -1
  15. package/lib/exercises/math/functions/trinoms/roots/rootsFromDevForm.js +41 -16
  16. package/lib/exercises/math/functions/trinoms/roots/rootsReading.d.ts.map +1 -1
  17. package/lib/exercises/math/functions/trinoms/roots/rootsReading.js +3 -2
  18. package/lib/exercises/math/functions/trinoms/sign/trinomSignFromFacto.d.ts +1 -0
  19. package/lib/exercises/math/functions/trinoms/sign/trinomSignFromFacto.d.ts.map +1 -1
  20. package/lib/exercises/math/functions/trinoms/sign/trinomSignFromFacto.js +21 -13
  21. package/lib/exercises/math/geometry/perimeters/circleCircumference.d.ts.map +1 -1
  22. package/lib/exercises/math/geometry/perimeters/circleCircumference.js +15 -7
  23. package/lib/exercises/math/geometry/shapes/basicShapesNaming.d.ts.map +1 -1
  24. package/lib/exercises/math/geometry/shapes/basicShapesNaming.js +5 -3
  25. package/lib/exercises/math/percent/evolutions/evolutionToCM.js +2 -2
  26. package/lib/exercises/math/percent/findProportion.d.ts +6 -1
  27. package/lib/exercises/math/percent/findProportion.d.ts.map +1 -1
  28. package/lib/exercises/math/percent/findProportion.js +162 -45
  29. package/lib/exercises/math/powers/calculateNegativePower.d.ts +5 -1
  30. package/lib/exercises/math/powers/calculateNegativePower.d.ts.map +1 -1
  31. package/lib/exercises/math/powers/calculateNegativePower.js +93 -29
  32. package/lib/exercises/math/probaStat/probaFromTableNoContext.d.ts.map +1 -1
  33. package/lib/exercises/math/probaStat/probaFromTableNoContext.js +10 -2
  34. package/lib/exercises/math/probaStat/probaFromTableWithContext.d.ts.map +1 -1
  35. package/lib/exercises/math/probaStat/probaFromTableWithContext.js +2 -1
  36. package/lib/exercises/math/probaStat/stats1var/quartilesList.d.ts +4 -1
  37. package/lib/exercises/math/probaStat/stats1var/quartilesList.d.ts.map +1 -1
  38. package/lib/exercises/math/probaStat/stats1var/quartilesList.js +46 -27
  39. package/lib/exercises/math/sequences/geometric/geometricFindExplicitFormula.d.ts.map +1 -1
  40. package/lib/exercises/math/sequences/geometric/geometricFindExplicitFormula.js +14 -2
  41. package/lib/exercises/math/sequences/geometric/geometricReasonUsage.d.ts +1 -0
  42. package/lib/exercises/math/sequences/geometric/geometricReasonUsage.d.ts.map +1 -1
  43. package/lib/exercises/math/sequences/geometric/geometricReasonUsage.js +43 -19
  44. package/lib/exercises/math/sequences/sequenceEvaluation.d.ts.map +1 -1
  45. package/lib/exercises/math/sequences/sequenceEvaluation.js +18 -1
  46. package/lib/exercises/pc/chemicalReactions/chemicalEquations.d.ts.map +1 -1
  47. package/lib/exercises/pc/chemicalReactions/chemicalEquations.js +17 -2
  48. package/lib/exercises/pc/mole/molarMass.d.ts.map +1 -1
  49. package/lib/exercises/pc/mole/molarMass.js +7 -1
  50. package/lib/exercises/pc/motion/averageSpeed.d.ts +9 -4
  51. package/lib/exercises/pc/motion/averageSpeed.d.ts.map +1 -1
  52. package/lib/exercises/pc/motion/averageSpeed.js +132 -61
  53. package/lib/exercises/pc/motion/averageSpeedCalculation.d.ts.map +1 -1
  54. package/lib/exercises/pc/motion/averageSpeedCalculation.js +10 -4
  55. package/lib/exercises/pc/recognizeRefractionOrReflectionAngles.d.ts +2 -2
  56. package/lib/exercises/pc/recognizeRefractionOrReflectionAngles.js +15 -15
  57. package/lib/exercises/utils/geogebra/toolBarConstructor.d.ts +1 -0
  58. package/lib/exercises/utils/geogebra/toolBarConstructor.d.ts.map +1 -1
  59. package/lib/exercises/utils/geogebra/toolBarConstructor.js +3 -1
  60. package/lib/index.d.ts +46 -11
  61. package/lib/index.d.ts.map +1 -1
  62. package/lib/pc/units/timeUnits.d.ts +5 -3
  63. package/lib/pc/units/timeUnits.d.ts.map +1 -1
  64. package/lib/pc/units/timeUnits.js +25 -19
  65. package/package.json +1 -1
@@ -3,7 +3,7 @@ type Identifiers = {
3
3
  nb: number;
4
4
  };
5
5
  type Options = {
6
- usePowers?: boolean;
6
+ asPowers?: boolean;
7
7
  };
8
8
  export declare const primeNumbers: Exercise<Identifiers, Options>;
9
9
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"primeNumbers.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/calcul/arithmetics/primeNumbers.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,QAAQ,EAkBT,MAAM,sBAAsB,CAAC;AAmB9B,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAmMF,KAAK,OAAO,GAAG;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAWF,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAgBvD,CAAC"}
1
+ {"version":3,"file":"primeNumbers.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/calcul/arithmetics/primeNumbers.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,QAAQ,EAkBT,MAAM,sBAAsB,CAAC;AAmB9B,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAsMF,KAAK,OAAO,GAAG;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAcF,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAgBvD,CAAC"}
@@ -26,14 +26,16 @@ const getInstruction = (identifiers) => {
26
26
 
27
27
  $$
28
28
  ${getStartStatement(identifiers)}
29
- $$`;
29
+ $$
30
+
31
+ `;
30
32
  };
31
33
  const getAnswer = (identifiers, opts) => {
32
34
  const { nb } = identifiers;
33
35
  const decomp = primeDecomposition(nb);
34
- const usePowers = opts?.usePowers;
36
+ const asPowers = opts?.asPowers;
35
37
  const nodes = [];
36
- if (usePowers) {
38
+ if (asPowers) {
37
39
  for (const d of decomp) {
38
40
  if (d.power === 1)
39
41
  nodes.push(d.value.toTree());
@@ -50,7 +52,8 @@ const getAnswer = (identifiers, opts) => {
50
52
  }
51
53
  return operatorComposition(MultiplyNode, nodes).toTex();
52
54
  };
53
- const getPrimeNumbers = (opts) => {
55
+ const getPrimeNumbers = (optsIn) => {
56
+ const opts = optsIn ?? optsDefault;
54
57
  const rand = randint(2, 5);
55
58
  let nb = 0;
56
59
  let counter = 0;
@@ -71,16 +74,16 @@ const getPrimeNumbers = (opts) => {
71
74
  const getHint = (identifiers) => {
72
75
  return `Les premiers nombres premiers sont : $2$, $3$, $5$, $7$, $11$.
73
76
 
74
- Essaie de diviser le nombre $${identifiers.nb}$ par ces nombres.`;
77
+ On peut essayer de diviser le nombre $${identifiers.nb}$ par ces nombres.`;
75
78
  };
76
79
  const getCorrection = (identifiers, opts) => {
77
80
  const { nb } = identifiers;
78
81
  let n = nb;
79
82
  const list = [];
80
- const usePowers = opts?.usePowers;
81
- const answerPowers = usePowers ? getAnswer(identifiers, opts) : undefined;
82
- const answerNoPowers = getAnswer(identifiers, { usePowers: false });
83
- const powerIsDifferent = !usePowers ? false : answerPowers !== answerNoPowers;
83
+ const asPowers = opts?.asPowers;
84
+ const answerPowers = asPowers ? getAnswer(identifiers, opts) : undefined;
85
+ const answerNoPowers = getAnswer(identifiers, { asPowers: false });
86
+ const powerIsDifferent = !asPowers ? false : answerPowers !== answerNoPowers;
84
87
  for (const k of [2, 3, 5, 7, 11]) {
85
88
  let counter = 0;
86
89
  while (n % k === 0) {
@@ -98,7 +101,7 @@ ${alignTex(list)}
98
101
  On prend alors la liste des quotients :
99
102
 
100
103
  $$
101
- ${nb.frenchify()} = ${answerNoPowers} ${powerIsDifferent ? `=${answerPowers}` : ""}
104
+ ${nb.frenchify()} = ${answerNoPowers} ${powerIsDifferent && asPowers ? `=${answerPowers}` : ""}
102
105
  $$
103
106
  `;
104
107
  };
@@ -152,7 +155,7 @@ const isAnswerValid = (ans, { nb }) => {
152
155
  try {
153
156
  //? aucune idée de comment, mais les élèves envoient parfois des espaces
154
157
  const parsed = parseAlgebraic(ans.replaceAll("\\ ", ""));
155
- if (!isMultiplyNode(parsed))
158
+ if (!(isMultiplyNode(parsed) || isPowerNode(parsed)))
156
159
  return false;
157
160
  const externals = [];
158
161
  const recur = (node) => {
@@ -192,13 +195,16 @@ const isAnswerValid = (ans, { nb }) => {
192
195
  return handleVEAError(err);
193
196
  }
194
197
  };
198
+ const optsDefault = {
199
+ asPowers: true,
200
+ };
195
201
  const options = [
196
202
  {
197
- id: "usePowers",
198
- label: "Utiliser des puissances",
203
+ id: "asPowers",
204
+ label: "correction avec des puissances",
199
205
  target: GeneratorOptionTarget.answer,
200
206
  type: GeneratorOptionType.checkbox,
201
- defaultValue: false,
207
+ defaultValue: optsDefault.asPowers,
202
208
  },
203
209
  ];
204
210
  export const primeNumbers = {
@@ -44,7 +44,7 @@ const getAnswer = (identifiers) => {
44
44
  return statement.simplify().toTex();
45
45
  };
46
46
  const getInstruction = (identifiers) => {
47
- return `Écrire sous la forme d'une fraction irréductible :
47
+ return `Écrire sous la forme d'une fraction irréductible ou d'un entier :
48
48
 
49
49
  $$
50
50
  ${getStatement(identifiers).toTex()}
@@ -1 +1 @@
1
- {"version":3,"file":"volumeConversion.d.ts","sourceRoot":"","sources":["../../../../src/exercises/math/conversion/volumeConversion.ts"],"names":[],"mappings":"AAUA,OAAO,EACL,QAAQ,EAcT,MAAM,mBAAmB,CAAC;AAE3B,KAAK,WAAW,GAAG;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,0BAA0B,EAAE,MAAM,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAgIF,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,WAAW,CAclD,CAAC"}
1
+ {"version":3,"file":"volumeConversion.d.ts","sourceRoot":"","sources":["../../../../src/exercises/math/conversion/volumeConversion.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,QAAQ,EAcT,MAAM,mBAAmB,CAAC;AAE3B,KAAK,WAAW,GAAG;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,0BAA0B,EAAE,MAAM,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAwIF,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,WAAW,CAclD,CAAC"}
@@ -2,6 +2,8 @@ import { Decimal, DecimalConstructor, } from "../../../math/numbers/decimals/dec
2
2
  import { randint } from "../../../math/utils/random/randint.js";
3
3
  import { frac } from "../../../tree/nodes/operators/fractionNode.js";
4
4
  import { multiply } from "../../../tree/nodes/operators/multiplyNode.js";
5
+ import { substract } from "../../../tree/nodes/operators/substractNode.js";
6
+ import { parseAlgebraic } from "../../../tree/parsers/latexParser.js";
5
7
  import { shuffle } from "../../../utils/alea/shuffle.js";
6
8
  import { doWhile } from "../../../utils/doWhile.js";
7
9
  import { alignTex } from "../../../utils/latex/alignTex.js";
@@ -99,7 +101,11 @@ const getPropositions = (n, { answer, randomUnitIndex, randomUnitInstructionInde
99
101
  return shuffle(propositions);
100
102
  };
101
103
  const isAnswerValid = (ans, { answer }) => {
102
- return ans === answer;
104
+ return (ans === answer ||
105
+ (() => {
106
+ const [nodeAns, nodeAnswer] = [ans, answer].map((tex) => parseAlgebraic(tex));
107
+ return substract(nodeAns, nodeAnswer).evaluate() === 0;
108
+ })());
103
109
  };
104
110
  export const volumeConversion = {
105
111
  id: "volumeConversion",
@@ -1 +1 @@
1
- {"version":3,"file":"expDerivativeFour.d.ts","sourceRoot":"","sources":["../../../../../../src/exercises/math/derivation/derivative/exp/expDerivativeFour.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAaT,MAAM,6BAA6B,CAAC;AAQrC,KAAK,WAAW,GAAG;IACjB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,CAAC;AAmFF,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,WAAW,CAenD,CAAC"}
1
+ {"version":3,"file":"expDerivativeFour.d.ts","sourceRoot":"","sources":["../../../../../../src/exercises/math/derivation/derivative/exp/expDerivativeFour.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAaT,MAAM,6BAA6B,CAAC;AAQrC,KAAK,WAAW,GAAG;IACjB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,CAAC;AA2FF,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,WAAW,CAenD,CAAC"}
@@ -18,12 +18,15 @@ f(x) = ${fct.toTex()}
18
18
  $$`;
19
19
  };
20
20
  const getAnswer = (identifiers) => {
21
+ return getAnswerNode(identifiers).toTex();
22
+ };
23
+ const getAnswerNode = (identifiers) => {
21
24
  const { affine1Coeffs, affine2Coeffs } = identifiers;
22
25
  const affine1 = new Affine(affine1Coeffs[1], affine1Coeffs[0]);
23
26
  const affine2 = new Affine(affine2Coeffs[1], affine2Coeffs[0]);
24
27
  const exp = new ExpNode(affine2.toTree());
25
28
  const deriv = new MultiplyNode(new Affine(affine2.a * affine1.a, affine1.a + affine2.a * affine1.b).toTree(), exp);
26
- return deriv.simplify().toTex();
29
+ return deriv.simplify();
27
30
  };
28
31
  const getExpDerivativeFourQuestion = () => {
29
32
  const affine1 = AffineConstructor.random();
@@ -53,12 +56,15 @@ const getPropositions = (n, { answer }) => {
53
56
  });
54
57
  return shuffleProps(propositions, n);
55
58
  };
56
- const isAnswerValid = (ans, { answer }) => {
59
+ const isAnswerValid = (ans, { answer, ...identifiers }) => {
57
60
  try {
58
61
  const parsed = parseAlgebraic(ans);
59
62
  if (!parsed)
60
63
  return false;
61
- return parsed.simplify().toTex() === answer;
64
+ // return parsed.simplify().toTex() === answer;
65
+ const ansTex = parsed.simplify().toTex();
66
+ const ansNode = getAnswerNode(identifiers);
67
+ return ansNode.toAllValidTexs().includes(ansTex);
62
68
  }
63
69
  catch (err) {
64
70
  return handleVEAError(err);
@@ -1,13 +1,13 @@
1
- import { isGGBLine } from "../../../../exercises/utils/geogebra/isGGBLine.js";
2
- import { isGGBPoint } from "../../../../exercises/utils/geogebra/isGGBPoint.js";
3
1
  import { toolBarConstructor } from "../../../../exercises/utils/geogebra/toolBarConstructor.js";
4
2
  import { getDistinctQuestions } from "../../../../exercises/utils/getDistinctQuestions.js";
5
- import { deleteObjectNamesFromAnswer } from "../../../../geogebra/deleteObjectNamesFromAnswer.js";
6
3
  import { GeogebraConstructor } from "../../../../geogebra/geogebraConstructor.js";
7
- import { approxEqual } from "../../../../geogebra/parsers/approxEqual.js";
8
- import { Point } from "../../../../math/geometry/point.js";
9
4
  import { Affine, AffineConstructor } from "../../../../math/polynomials/affine.js";
10
5
  import { random } from "../../../../utils/alea/random.js";
6
+ import { isGGBLine } from "../../../../exercises/utils/geogebra/isGGBLine.js";
7
+ import { isGGBPoint } from "../../../../exercises/utils/geogebra/isGGBPoint.js";
8
+ import { deleteObjectNamesFromAnswer } from "../../../../geogebra/deleteObjectNamesFromAnswer.js";
9
+ import { approxEqual } from "../../../../geogebra/parsers/approxEqual.js";
10
+ import { Point } from "../../../../math/geometry/point.js";
11
11
  import { arrayEqual } from "../../../../utils/arrays/arrayEqual.js";
12
12
  const getInstruction = (identifiers) => {
13
13
  const { correctA, correctB, nameFunc } = identifiers;
@@ -1 +1 @@
1
- {"version":3,"file":"findZeroesProductQuotient.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/basics/findZeroesProductQuotient.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAeT,MAAM,6BAA6B,CAAC;AAsBrC,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ,CAAC;AAkOF,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,WAAW,CAkB3D,CAAC"}
1
+ {"version":3,"file":"findZeroesProductQuotient.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/basics/findZeroesProductQuotient.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAeT,MAAM,6BAA6B,CAAC;AAuBrC,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ,CAAC;AA6QF,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,WAAW,CAkB3D,CAAC"}
@@ -153,17 +153,44 @@ $$
153
153
  const getKeys = () => {
154
154
  return ["S", "equal", "lbrace", "semicolon", "rbrace"];
155
155
  };
156
- const isAnswerValid = (ans, { answer }) => {
156
+ const isAnswerValid = (ans, { answer, ...identifiers }) => {
157
157
  try {
158
158
  const parsed = discreteSetParser(ans);
159
159
  if (!parsed)
160
160
  return false;
161
- return "S=" + parsed.simplify().toTex() === answer;
161
+ const roots = getRoots(identifiers).map((r) => r.simplify());
162
+ return isArrayOfNodesValid(parsed.elements, roots);
162
163
  }
163
164
  catch (err) {
164
165
  return handleVEAError(err);
165
166
  }
166
167
  };
168
+ const isArrayOfNodesValid = (arrAns, arrAnswer) => {
169
+ //tried with toAllValidTexs() but there is always an unhandled case
170
+ function isNodesEqual(node1, node2) {
171
+ return [1, 1_000, 1_000_000].every((factor) => substract(multiply(factor, node1), multiply(factor, node2)).evaluate() === 0);
172
+ }
173
+ const dictAnswer = Object.fromEntries(arrAnswer.map((node, i) => [i, node]));
174
+ let isValid = true;
175
+ for (let i = 0; i < arrAns.length; i++) {
176
+ const nodeAns = arrAns[i];
177
+ let isFound = false;
178
+ const keys = Object.keys(dictAnswer);
179
+ for (let j = 0; j < keys.length; j++) {
180
+ const key = keys[j];
181
+ const answerNode = dictAnswer[key];
182
+ if (isNodesEqual(nodeAns, answerNode)) {
183
+ isFound = true;
184
+ delete dictAnswer[key]; //one-to-one correspondence
185
+ break;
186
+ }
187
+ }
188
+ isValid = isValid && isFound;
189
+ if (!isValid)
190
+ break;
191
+ }
192
+ return isValid;
193
+ };
167
194
  const getFindZeroesProductQuotientQuestion = () => {
168
195
  const type = randint(0, 3);
169
196
  let a = 0;
@@ -1 +1 @@
1
- {"version":3,"file":"inverseImageFunctionGeogebra.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/basics/inverseImageFunctionGeogebra.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAeT,MAAM,6BAA6B,CAAC;AAcrC,KAAK,WAAW,GAAG;IAEjB,MAAM,EAAE,MAAM,CAAC;IAIf,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;CACpB,CAAC;AAuNF,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,WAAW,CAkB9D,CAAC"}
1
+ {"version":3,"file":"inverseImageFunctionGeogebra.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/basics/inverseImageFunctionGeogebra.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAeT,MAAM,6BAA6B,CAAC;AAcrC,KAAK,WAAW,GAAG;IAEjB,MAAM,EAAE,MAAM,CAAC;IAIf,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;CACpB,CAAC;AAyOF,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,WAAW,CAkB9D,CAAC"}
@@ -56,74 +56,85 @@ const getGGBOptions = (identifiers) => {
56
56
  });
57
57
  };
58
58
  const getInverseImageFunctionGeogebra = () => {
59
- const isLine = coinFlip();
60
- const hasAntecedent = probaFlip(0.8);
61
- // const isLine = false;
62
- // const hasAntecedent = true;
63
- let yValue;
64
- const points = [];
65
- if (isLine) {
66
- if (hasAntecedent) {
67
- yValue = randint(-6, 7);
68
- const xIsDecimal = probaFlip(0.3);
69
- const xValue = xIsDecimal
70
- ? randfloat(-6, 7, 2, [yValue])
71
- : randint(-6, 7, [yValue]);
72
- const wrongY = randint(-6, 7);
73
- points.push([xValue, yValue], [yValue, wrongY]);
74
- }
75
- else {
76
- yValue = randint(-6, 7, [0]);
77
- const constante = randint(-6, 7, [yValue]);
78
- points.push([0, constante], [1, constante]);
79
- }
80
- }
81
- else {
82
- if (hasAntecedent) {
83
- yValue = randint(-6, 7);
84
- const xIsDecimal = coinFlip();
85
- const xValue = xIsDecimal
86
- ? randfloat(-6, 7, 2, [yValue])
87
- : randint(-6, 7, [yValue]);
88
- const hasTwoAntecedents = probaFlip(0.8);
89
- if (hasTwoAntecedents) {
90
- const wrongY = randint(-6, 7, [yValue]);
91
- const secondAntecedentPoint = [
92
- randint(-6, 7, [xValue, yValue]),
93
- yValue,
94
- ];
95
- points.push([xValue, yValue], [yValue, wrongY], secondAntecedentPoint);
59
+ function generateIdentifiers() {
60
+ const isLine = coinFlip();
61
+ const hasAntecedent = probaFlip(0.8);
62
+ // const isLine = false;
63
+ // const hasAntecedent = true;
64
+ let yValue;
65
+ const points = [];
66
+ if (isLine) {
67
+ if (hasAntecedent) {
68
+ yValue = randint(-6, 7);
69
+ const xIsDecimal = probaFlip(0.3);
70
+ const xValue = xIsDecimal
71
+ ? randfloat(-6, 7, 2, [yValue])
72
+ : randint(-6, 7, [yValue]);
73
+ const wrongY = randint(-6, 7);
74
+ points.push([xValue, yValue], [yValue, wrongY]);
96
75
  }
97
76
  else {
98
- //(x,y) is summit
99
- const wrongY = randint(-6, 7, [yValue]);
100
- points.push([xValue, yValue], [yValue, wrongY], [2 * xValue - yValue, wrongY]);
77
+ yValue = randint(-6, 7, [0]);
78
+ const constante = randint(-6, 7, [yValue]);
79
+ points.push([0, constante], [1, constante]);
101
80
  }
102
81
  }
103
82
  else {
104
- yValue = randint(-8, 9);
105
- const wrongY = randint(-3, 4, [yValue, yValue - 1, yValue + 1]);
106
- const below = wrongY < yValue;
107
- const summit = [
108
- randint(-6, 7, [yValue]),
109
- below
110
- ? randint(wrongY + 1, yValue, [wrongY])
111
- : randint(yValue + 1, wrongY, [wrongY]),
112
- ];
113
- const thirdPoint = [2 * summit[0] - yValue, wrongY];
114
- //construire deux autrs points au pif avec y sous/audssu yValus
115
- points.push([yValue, wrongY], summit, thirdPoint);
83
+ if (hasAntecedent) {
84
+ yValue = randint(-6, 7);
85
+ const xIsDecimal = coinFlip();
86
+ const xValue = xIsDecimal
87
+ ? randfloat(-6, 7, 2, [yValue])
88
+ : randint(-6, 7, [yValue]);
89
+ const hasTwoAntecedents = probaFlip(0.8);
90
+ if (hasTwoAntecedents) {
91
+ const wrongY = randint(-6, 7, [yValue]);
92
+ const secondAntecedentPoint = [
93
+ randint(-6, 7, [xValue, yValue]),
94
+ yValue,
95
+ ];
96
+ points.push([xValue, yValue], [yValue, wrongY], secondAntecedentPoint);
97
+ }
98
+ else {
99
+ //(x,y) is summit
100
+ const wrongY = randint(-6, 7, [yValue]);
101
+ points.push([xValue, yValue], [yValue, wrongY], [2 * xValue - yValue, wrongY]);
102
+ }
103
+ }
104
+ else {
105
+ yValue = randint(-8, 9);
106
+ const wrongY = randint(-3, 4, [yValue, yValue - 1, yValue + 1]);
107
+ const below = wrongY < yValue;
108
+ const summit = [
109
+ randint(-6, 7, [yValue]),
110
+ below
111
+ ? randint(wrongY + 1, yValue, [wrongY])
112
+ : randint(yValue + 1, wrongY, [wrongY]),
113
+ ];
114
+ const thirdPoint = [2 * summit[0] - yValue, wrongY];
115
+ //construire deux autrs points au pif avec y sous/audssu yValus
116
+ points.push([yValue, wrongY], summit, thirdPoint);
117
+ }
116
118
  }
119
+ points.sort((p1, p2) => p1[0] - p2[0]);
120
+ const identifiers = {
121
+ // xValue,
122
+ // affineCoeffs: isAffine ? affine!.coefficients : undefined,
123
+ // trinomCoeffs: isAffine ? undefined : trinom!.coefficients,
124
+ yValue,
125
+ points,
126
+ // isAffine,
127
+ };
128
+ return identifiers;
117
129
  }
118
- points.sort((p1, p2) => p1[0] - p2[0]);
119
- const identifiers = {
120
- // xValue,
121
- // affineCoeffs: isAffine ? affine!.coefficients : undefined,
122
- // trinomCoeffs: isAffine ? undefined : trinom!.coefficients,
123
- yValue,
124
- points,
125
- // isAffine,
126
- };
130
+ function isInfinityOfSolutions(identifiers) {
131
+ const { yValue, points } = identifiers;
132
+ return points.every((point) => point[1] === yValue);
133
+ }
134
+ let identifiers;
135
+ do {
136
+ identifiers = generateIdentifiers();
137
+ } while (isInfinityOfSolutions(identifiers));
127
138
  return getQuestionFromIdentifiers(identifiers);
128
139
  };
129
140
  const getHint = (identifiers) => {
@@ -1 +1 @@
1
- {"version":3,"file":"rootsFromDevForm.d.ts","sourceRoot":"","sources":["../../../../../../src/exercises/math/functions/trinoms/roots/rootsFromDevForm.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAYT,MAAM,6BAA6B,CAAC;AASrC,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAwEF,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,WAAW,CAalD,CAAC"}
1
+ {"version":3,"file":"rootsFromDevForm.d.ts","sourceRoot":"","sources":["../../../../../../src/exercises/math/functions/trinoms/roots/rootsFromDevForm.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAYT,MAAM,6BAA6B,CAAC;AAYrC,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AA4GF,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,WAAW,CAalD,CAAC"}
@@ -2,9 +2,11 @@ import { addValidProp, propWhile, tryToAddWrongProp, } from "../../../../../exer
2
2
  import { getDistinctQuestions } from "../../../../../exercises/utils/getDistinctQuestions.js";
3
3
  import { Trinom, TrinomConstructor } from "../../../../../math/polynomials/trinom.js";
4
4
  import { randint } from "../../../../../math/utils/random/randint.js";
5
- import { EquationSolutionNode } from "../../../../../tree/nodes/equations/equationSolutionNode.js";
6
- import { DiscreteSetNode } from "../../../../../tree/nodes/sets/discreteSetNode.js";
5
+ import { multiply } from "../../../../../tree/nodes/operators/multiplyNode.js";
6
+ import { substract } from "../../../../../tree/nodes/operators/substractNode.js";
7
+ import { discreteSetParser } from "../../../../../tree/parsers/discreteSetParser.js";
7
8
  import { shuffle } from "../../../../../utils/alea/shuffle.js";
9
+ import { handleVEAError } from "../../../../../utils/errors/handleVEAError.js";
8
10
  const getInstruction = (identifiers) => {
9
11
  const { a, b, c } = identifiers;
10
12
  const trinom = new Trinom(a, b, c);
@@ -49,20 +51,43 @@ const getPropositions = (n, { answer }) => {
49
51
  return shuffle(propositions);
50
52
  };
51
53
  const isAnswerValid = (ans, { a, b, c }) => {
52
- // try {
53
- // const parsed = discreteSetParser(ans);
54
- // if (!parsed) return false;
55
- // return (
56
- // "S=" + parsed.simplify({ decimalToFractions: true }).toTex() === answer
57
- // );
58
- // } catch (err) {
59
- // return handleVEAError(err);
60
- // }
61
- const trinom = new Trinom(a, b, c);
62
- const roots = trinom.getRootsNode();
63
- const answer = new EquationSolutionNode(new DiscreteSetNode(roots));
64
- const texs = answer.toAllValidTexs();
65
- return texs.includes(ans);
54
+ try {
55
+ const parsed = discreteSetParser(ans);
56
+ if (!parsed)
57
+ return false;
58
+ const trinom = new Trinom(a, b, c);
59
+ const roots = trinom.getRootsNode();
60
+ return isArrayOfNodesValid(parsed.elements, roots);
61
+ }
62
+ catch (err) {
63
+ return handleVEAError(err);
64
+ }
65
+ };
66
+ const isArrayOfNodesValid = (arrAns, arrAnswer) => {
67
+ //tried with toAllValidTexs() but there is always an unhandled case
68
+ function isNodesEqual(node1, node2) {
69
+ return [1, 1_000, 1_000_000].every((factor) => substract(multiply(factor, node1), multiply(factor, node2)).evaluate() === 0);
70
+ }
71
+ const dictAnswer = Object.fromEntries(arrAnswer.map((node, i) => [i, node]));
72
+ let isValid = true;
73
+ for (let i = 0; i < arrAns.length; i++) {
74
+ const nodeAns = arrAns[i];
75
+ let isFound = false;
76
+ const keys = Object.keys(dictAnswer);
77
+ for (let j = 0; j < keys.length; j++) {
78
+ const key = keys[j];
79
+ const answerNode = dictAnswer[key];
80
+ if (isNodesEqual(nodeAns, answerNode)) {
81
+ isFound = true;
82
+ delete dictAnswer[key]; //one-to-one correspondence
83
+ break;
84
+ }
85
+ }
86
+ isValid = isValid && isFound;
87
+ if (!isValid)
88
+ break;
89
+ }
90
+ return isValid;
66
91
  };
67
92
  export const rootsFromDevForm = {
68
93
  id: "rootsFromDevForm",
@@ -1 +1 @@
1
- {"version":3,"file":"rootsReading.d.ts","sourceRoot":"","sources":["../../../../../../src/exercises/math/functions/trinoms/roots/rootsReading.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAcT,MAAM,6BAA6B,CAAC;AAUrC,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAmGF,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,WAAW,CAY9C,CAAC"}
1
+ {"version":3,"file":"rootsReading.d.ts","sourceRoot":"","sources":["../../../../../../src/exercises/math/functions/trinoms/roots/rootsReading.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAcT,MAAM,6BAA6B,CAAC;AAUrC,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX,CAAC;AAoGF,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,WAAW,CAY9C,CAAC"}
@@ -80,8 +80,9 @@ const isAnswerValid = (ans, { a, b, c }) => {
80
80
  return ans === "\\text{Aucun}";
81
81
  }
82
82
  const studentNumbers = ans
83
- .replaceAll("\\text{ }", "")
84
- .split("\\text{ et }")
83
+ .replaceAll("\\text{", "")
84
+ .replaceAll("}", "") //as long as there's no \\frac{}{} involved, it's ok
85
+ .split("et")
85
86
  .map((n) => Number(n.replace(",", ".")))
86
87
  .filter((n) => !isNaN(n))
87
88
  .sort((a, b) => a - b);
@@ -2,6 +2,7 @@ import { Exercise } from "../../../../../exercises/exercise.js";
2
2
  type Identifiers = {
3
3
  trinomCoeffs: number[];
4
4
  isAskingPositive: boolean;
5
+ isStrict: boolean;
5
6
  };
6
7
  export declare const trinomSignFromFacto: Exercise<Identifiers>;
7
8
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"trinomSignFromFacto.d.ts","sourceRoot":"","sources":["../../../../../../src/exercises/math/functions/trinoms/sign/trinomSignFromFacto.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAgBT,MAAM,6BAA6B,CAAC;AAkBrC,KAAK,WAAW,GAAG;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;CAC3B,CAAC;AAyHF,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,WAAW,CAqBrD,CAAC"}
1
+ {"version":3,"file":"trinomSignFromFacto.d.ts","sourceRoot":"","sources":["../../../../../../src/exercises/math/functions/trinoms/sign/trinomSignFromFacto.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAgBT,MAAM,6BAA6B,CAAC;AAkBrC,KAAK,WAAW,GAAG;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAgJF,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,WAAW,CAqBrD,CAAC"}
@@ -8,11 +8,12 @@ import { UnionIntervalNode } from "../../../../../tree/nodes/sets/unionIntervalN
8
8
  import { coinFlip } from "../../../../../utils/alea/coinFlip.js";
9
9
  import { unionIntervalParser } from "../../../../../tree/parsers/unionIntervalParser.js";
10
10
  import { handleVEAError } from "../../../../../utils/errors/handleVEAError.js";
11
- const getPropositions = (n, { answer, trinomCoeffs, isAskingPositive }) => {
11
+ const getPropositions = (n, { answer, trinomCoeffs, isAskingPositive, isStrict }) => {
12
12
  const propositions = [];
13
13
  addValidProp(propositions, answer);
14
14
  const trinom = TrinomNodeConstructor.fromCoeffs(trinomCoeffs);
15
- tryToAddWrongProp(propositions, getAnswer({ trinomCoeffs, isAskingPositive: !isAskingPositive }));
15
+ tryToAddWrongProp(propositions, getAnswer({ trinomCoeffs, isAskingPositive: !isAskingPositive, isStrict }));
16
+ tryToAddWrongProp(propositions, getAnswer({ trinomCoeffs, isAskingPositive, isStrict: !isStrict }));
16
17
  tryToAddWrongProp(propositions, new IntervalNode(trinom.a, trinom.b, ClosureType.FF).toTex());
17
18
  propWhile(propositions, n, () => {
18
19
  const interval = IntervalNodeConstructor.random();
@@ -21,36 +22,41 @@ const getPropositions = (n, { answer, trinomCoeffs, isAskingPositive }) => {
21
22
  return shuffleProps(propositions, n);
22
23
  };
23
24
  const getAnswerNode = (identifiers) => {
24
- const trinom = TrinomNodeConstructor.fromCoeffs(identifiers.trinomCoeffs);
25
+ const { trinomCoeffs, isAskingPositive, isStrict } = identifiers;
26
+ const trinom = TrinomNodeConstructor.fromCoeffs(trinomCoeffs);
25
27
  const roots = trinom.getRoots();
26
- const a = identifiers.trinomCoeffs[2];
27
- return a > 0 === identifiers.isAskingPositive
28
+ const a = trinomCoeffs[2];
29
+ return a > 0 === isAskingPositive
28
30
  ? new UnionIntervalNode([
29
- new IntervalNode(MinusInfinityNode, roots[0], ClosureType.OF),
30
- new IntervalNode(roots[1], PlusInfinityNode, ClosureType.FO),
31
+ new IntervalNode(MinusInfinityNode, roots[0], isStrict ? ClosureType.OO : ClosureType.OF),
32
+ new IntervalNode(roots[1], PlusInfinityNode, isStrict ? ClosureType.OO : ClosureType.FO),
31
33
  ])
32
- : new IntervalNode(roots[0], roots[1], ClosureType.FF);
34
+ : new IntervalNode(roots[0], roots[1], isStrict ? ClosureType.OO : ClosureType.FF);
33
35
  };
34
36
  const getAnswer = (identifiers) => {
35
37
  return getAnswerNode(identifiers).toTex();
36
38
  };
37
39
  const getInstruction = (identifiers) => {
38
- const trinom = TrinomNodeConstructor.fromCoeffs(identifiers.trinomCoeffs);
40
+ const { trinomCoeffs, isAskingPositive, isStrict } = identifiers;
41
+ const trinom = TrinomNodeConstructor.fromCoeffs(trinomCoeffs);
39
42
  return `Soit $f$ une fonction polynôme de degré $2$ définie sur $\\mathbb{R}$ par :
40
43
 
41
44
  $$
42
45
  f(x) = ${trinom.toFactorized().toTex()}
43
46
  $$
44
47
 
45
- Sur quel(s) intervalle(s) les valeurs de la fonction $f$ sont-elles ${identifiers.isAskingPositive ? "positives" : "négatives"} ?`;
48
+ Sur quel(s) intervalle(s) les valeurs de la fonction $f$ sont-elles
49
+ ${isStrict ? "strictement" : ""} ${isAskingPositive ? "positives" : "négatives"}
50
+ ?`;
46
51
  };
47
52
  const getHint = () => {
48
53
  return `Une fonction polynôme de degré $2$ est du signe de son coefficient $a$, sauf entre ses racines.`;
49
54
  };
50
55
  const getCorrection = (identifiers) => {
51
- const trinom = TrinomNodeConstructor.fromCoeffs(identifiers.trinomCoeffs);
56
+ const { trinomCoeffs, isAskingPositive, isStrict } = identifiers;
57
+ const trinom = TrinomNodeConstructor.fromCoeffs(trinomCoeffs);
52
58
  const roots = trinom.getRoots();
53
- const a = identifiers.trinomCoeffs[2];
59
+ const a = trinomCoeffs[2];
54
60
  const answer = getAnswer(identifiers);
55
61
  const ineqSign = a > 0 ? ">" : "<";
56
62
  const sign = a > 0 ? "positive" : "négative";
@@ -60,7 +66,7 @@ Ici, $a = ${a}${ineqSign}0$, et les racines de $f$ sont $${roots[0].toTex()}$ et
60
66
 
61
67
  $f$ est donc ${sign} sauf sur l'intervalle $${new IntervalNode(roots[0], roots[1], ClosureType.FF).toTex()}$.
62
68
 
63
- On en déduit que $f$ est ${identifiers.isAskingPositive ? "positive" : "négative"} sur :
69
+ On en déduit que $f$ est ${isStrict ? "strictement" : ""} ${isAskingPositive ? "positive" : "négative"} sur :
64
70
 
65
71
  $$
66
72
  ${answer}
@@ -83,8 +89,10 @@ const isAnswerValid = (ans, { answer }) => {
83
89
  const getTrinomSignFromFactoQuestion = () => {
84
90
  const trinom = TrinomNodeConstructor.randomNiceRoots(2);
85
91
  const isAskingPositive = coinFlip();
92
+ const isStrict = coinFlip();
86
93
  const identifiers = {
87
94
  isAskingPositive,
95
+ isStrict,
88
96
  trinomCoeffs: trinom.getCoeffs(),
89
97
  };
90
98
  return getQuestionFromIdentifiers(identifiers);
@@ -1 +1 @@
1
- {"version":3,"file":"circleCircumference.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/perimeters/circleCircumference.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAcT,MAAM,6BAA6B,CAAC;AAMrC,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAoGF,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,WAAW,CAcrD,CAAC"}
1
+ {"version":3,"file":"circleCircumference.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/perimeters/circleCircumference.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAcT,MAAM,6BAA6B,CAAC;AAQrC,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AA2GF,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,WAAW,CAcrD,CAAC"}