math-exercises 3.0.123 → 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 (75) 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/affineFromExercise.d.ts +1 -1
  10. package/lib/exercises/math/functions/affines/affineFromExercise.d.ts.map +1 -1
  11. package/lib/exercises/math/functions/affines/affineFromExercise.js +123 -48
  12. package/lib/exercises/math/functions/affines/drawAffineFromLitExp.js +5 -5
  13. package/lib/exercises/math/functions/affines/recognizeAffineGraph.d.ts +2 -1
  14. package/lib/exercises/math/functions/affines/recognizeAffineGraph.d.ts.map +1 -1
  15. package/lib/exercises/math/functions/affines/recognizeAffineGraph.js +41 -24
  16. package/lib/exercises/math/functions/basics/findZeroesProductQuotient.d.ts.map +1 -1
  17. package/lib/exercises/math/functions/basics/findZeroesProductQuotient.js +29 -2
  18. package/lib/exercises/math/functions/basics/inverseImageFunctionGeogebra.d.ts.map +1 -1
  19. package/lib/exercises/math/functions/basics/inverseImageFunctionGeogebra.js +72 -61
  20. package/lib/exercises/math/functions/logarithm/powerEquation.d.ts.map +1 -1
  21. package/lib/exercises/math/functions/logarithm/powerEquation.js +0 -1
  22. package/lib/exercises/math/functions/trinoms/roots/rootsFromDevForm.d.ts.map +1 -1
  23. package/lib/exercises/math/functions/trinoms/roots/rootsFromDevForm.js +41 -16
  24. package/lib/exercises/math/functions/trinoms/roots/rootsReading.d.ts.map +1 -1
  25. package/lib/exercises/math/functions/trinoms/roots/rootsReading.js +3 -2
  26. package/lib/exercises/math/functions/trinoms/sign/trinomSignFromFacto.d.ts +1 -0
  27. package/lib/exercises/math/functions/trinoms/sign/trinomSignFromFacto.d.ts.map +1 -1
  28. package/lib/exercises/math/functions/trinoms/sign/trinomSignFromFacto.js +21 -13
  29. package/lib/exercises/math/geometry/perimeters/circleCircumference.d.ts.map +1 -1
  30. package/lib/exercises/math/geometry/perimeters/circleCircumference.js +15 -7
  31. package/lib/exercises/math/geometry/shapes/basicShapesNaming.d.ts.map +1 -1
  32. package/lib/exercises/math/geometry/shapes/basicShapesNaming.js +5 -3
  33. package/lib/exercises/math/geometry/vectors/vectorLinearCombination.d.ts.map +1 -1
  34. package/lib/exercises/math/geometry/vectors/vectorLinearCombination.js +0 -1
  35. package/lib/exercises/math/percent/evolutions/evolutionToCM.js +2 -2
  36. package/lib/exercises/math/percent/findProportion.d.ts +6 -1
  37. package/lib/exercises/math/percent/findProportion.d.ts.map +1 -1
  38. package/lib/exercises/math/percent/findProportion.js +162 -45
  39. package/lib/exercises/math/powers/calculateNegativePower.d.ts +5 -1
  40. package/lib/exercises/math/powers/calculateNegativePower.d.ts.map +1 -1
  41. package/lib/exercises/math/powers/calculateNegativePower.js +93 -29
  42. package/lib/exercises/math/probaStat/probaFromTableNoContext.d.ts.map +1 -1
  43. package/lib/exercises/math/probaStat/probaFromTableNoContext.js +10 -2
  44. package/lib/exercises/math/probaStat/probaFromTableWithContext.d.ts.map +1 -1
  45. package/lib/exercises/math/probaStat/probaFromTableWithContext.js +2 -1
  46. package/lib/exercises/math/probaStat/stats1var/quartilesList.d.ts +4 -1
  47. package/lib/exercises/math/probaStat/stats1var/quartilesList.d.ts.map +1 -1
  48. package/lib/exercises/math/probaStat/stats1var/quartilesList.js +46 -27
  49. package/lib/exercises/math/sequences/geometric/geometricFindExplicitFormula.d.ts.map +1 -1
  50. package/lib/exercises/math/sequences/geometric/geometricFindExplicitFormula.js +14 -2
  51. package/lib/exercises/math/sequences/geometric/geometricReasonUsage.d.ts +1 -0
  52. package/lib/exercises/math/sequences/geometric/geometricReasonUsage.d.ts.map +1 -1
  53. package/lib/exercises/math/sequences/geometric/geometricReasonUsage.js +43 -19
  54. package/lib/exercises/math/sequences/sequenceEvaluation.d.ts.map +1 -1
  55. package/lib/exercises/math/sequences/sequenceEvaluation.js +18 -1
  56. package/lib/exercises/pc/chemicalReactions/chemicalEquations.d.ts.map +1 -1
  57. package/lib/exercises/pc/chemicalReactions/chemicalEquations.js +17 -2
  58. package/lib/exercises/pc/mole/molarMass.d.ts.map +1 -1
  59. package/lib/exercises/pc/mole/molarMass.js +7 -1
  60. package/lib/exercises/pc/motion/averageSpeed.d.ts +9 -4
  61. package/lib/exercises/pc/motion/averageSpeed.d.ts.map +1 -1
  62. package/lib/exercises/pc/motion/averageSpeed.js +132 -61
  63. package/lib/exercises/pc/motion/averageSpeedCalculation.d.ts.map +1 -1
  64. package/lib/exercises/pc/motion/averageSpeedCalculation.js +10 -4
  65. package/lib/exercises/pc/recognizeRefractionOrReflectionAngles.d.ts +2 -2
  66. package/lib/exercises/pc/recognizeRefractionOrReflectionAngles.js +15 -15
  67. package/lib/exercises/utils/geogebra/toolBarConstructor.d.ts +1 -0
  68. package/lib/exercises/utils/geogebra/toolBarConstructor.d.ts.map +1 -1
  69. package/lib/exercises/utils/geogebra/toolBarConstructor.js +3 -1
  70. package/lib/index.d.ts +49 -13
  71. package/lib/index.d.ts.map +1 -1
  72. package/lib/pc/units/timeUnits.d.ts +5 -3
  73. package/lib/pc/units/timeUnits.d.ts.map +1 -1
  74. package/lib/pc/units/timeUnits.js +25 -19
  75. 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,6 +1,6 @@
1
1
  import { Exercise } from "../../../../exercises/exercise.js";
2
2
  type Identifiers = {
3
- phrase: number;
3
+ situationIndex: number;
4
4
  initial: number;
5
5
  growth: number;
6
6
  };
@@ -1 +1 @@
1
- {"version":3,"file":"affineFromExercise.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/affines/affineFromExercise.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAaT,MAAM,6BAA6B,CAAC;AASrC,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAuHF,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,WAAW,CAiBpD,CAAC"}
1
+ {"version":3,"file":"affineFromExercise.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/affines/affineFromExercise.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAaT,MAAM,6BAA6B,CAAC;AASrC,KAAK,WAAW,GAAG;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAoNF,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,WAAW,CAiBpD,CAAC"}
@@ -6,6 +6,114 @@ import { add } from "../../../../tree/nodes/operators/addNode.js";
6
6
  import { multiply } from "../../../../tree/nodes/operators/multiplyNode.js";
7
7
  import { VariableNode } from "../../../../tree/nodes/variables/variableNode.js";
8
8
  import { parseAlgebraic } from "../../../../tree/parsers/latexParser.js";
9
+ const situations = [
10
+ {
11
+ instruction: (initial, growth) => `On suppose qu'une plante, d'une hauteur initiale de
12
+ $${initial.frenchify()}\\ \\textrm{cm}$, croît chaque jour de $${growth.frenchify()}\\ \\textrm{cm}$.
13
+ Quelle est sa hauteur (en $\\textrm{cm}$) après $x$ jours ?`,
14
+ hint: `Quel calcul permet de trouver la hauteur de la plante au bout de $10$ jours ?
15
+
16
+ Inspire toi de ce calcul pour déterminer la hauteur de la plante au bout de $x$ jours.`,
17
+ correction: (initial, growth, answer) => `Chaque jour, la plante gagne $${growth.frenchify()}\\ \\textrm{cm}$. Au bout de $x$ jours, la plante a donc gagné $x\\times ${growth.frenchify()}\\ \\textrm{cm}$.
18
+
19
+ La hauteur initiale de la plante est de $${initial}\\ \\textrm{cm}$.
20
+
21
+ Au bout de $x$ jours, la plante a donc une hauteur de :
22
+
23
+ $$
24
+ ${answer}\\ \\textrm{cm}
25
+ $$`,
26
+ randInitial: () => randint(2, 20),
27
+ randGrowth: () => randfloat(0, 4, 2, [0]),
28
+ },
29
+ {
30
+ instruction: (initial, growth) => `Une compagnie de taxis propose un tarif qui inclut un
31
+ montant fixe de $${initial.frenchify()}\\ €$ et un montant variable de $${growth.frenchify()}\\ €$
32
+ par kilomètre parcouru.
33
+ Quel est le prix payé (en $€$) pour $x \\ \\textrm{km}$ parcourus ?`,
34
+ hint: `Quel calcul permet de trouver le prix payé pour $10$ kilomètres parcourus ?
35
+
36
+ Inspire toi de ce calcul pour déterminer le prix payé pour $x$ kilomètres parcourus.
37
+ `,
38
+ correction: (initial, growth, answer) => `Pour chaque kilomètre parcouru, le prix augmente de $${growth.frenchify()}\\ €$. Au bout de $x$ kilomètres, le prix augmente donc de $x\\times ${growth.frenchify()}\\ \\ €$.
39
+
40
+ Le montant fixe initial du trajet est de $${initial}\\ €$.
41
+
42
+ Pour $x$ kilomètres parcourus, le prix du trajet est donc de :
43
+
44
+ $$
45
+ ${answer}\\ €
46
+ $$`,
47
+ randInitial: () => randint(2, 20),
48
+ randGrowth: () => randfloat(0, 4, 2, [0]),
49
+ },
50
+ {
51
+ instruction: (initial, growth) => `Pour l’électricité de sa maison, Jimmy paye
52
+ un abonnement fixe de $${initial.frenchify()}\\ €$
53
+ puis il paye $${growth.frenchify()}\\ €$ par kWh consommé.
54
+ Quelle sera la facture (en $€$) pour $x \\ \\textrm{kWh}$ consommés ?`,
55
+ hint: `Quel calcul permet de trouver la facture pour $10$ kWh consommés ?
56
+
57
+ Inspire toi de ce calcul pour déterminer la facture pour $x$ kWh consommés.
58
+ `,
59
+ correction: (initial, growth, answer) => `Pour chaque kWh consommé, le prix augmente de $${growth.frenchify()}\\ €$.
60
+ Au bout de $x$ kWh, le prix augmente donc de $x\\times ${growth.frenchify()}\\ \\ €$.
61
+
62
+ Le montant de l'abonnement fixe est de $${initial}\\ €$.
63
+
64
+ Pour $x$ kWh consommés, la facture sera donc de :
65
+
66
+ $$
67
+ ${answer}\\ €
68
+ $$`,
69
+ randInitial: () => randint(10, 20),
70
+ randGrowth: () => randfloat(0, 0.5, 2, [0]),
71
+ },
72
+ {
73
+ instruction: (initial, growth) => `Dany décide de partir au Sud de la France.
74
+ Il part de Valenciennes où il fait $${initial.frenchify()}$°C.
75
+ La température augmente de $${growth.frenchify()}$°C à chaque centaine de km vers le Sud.
76
+ Quelle sera la température (en °C) pour $x$ centaines de km parcourus vers le Sud ?`,
77
+ hint: `Quel calcul permet de trouver la température pour $2$ centaines de km parcourus ?
78
+
79
+ Inspire toi de ce calcul pour déterminer la température pour $x$ centaines de km parcourus.
80
+ `,
81
+ correction: (initial, growth, answer) => `Pour chaque centaine de km parcourue, la température augmente de $${growth.frenchify()}$ °C.
82
+ Au bout de $x$ centaines de km, la température augmente donc de $x\\times ${growth.frenchify()}$ °C.
83
+
84
+ Au départ, la température est de $${initial}$ °C.
85
+
86
+ Pour $x$ centaines de km parcourus, la température sera donc de :
87
+
88
+ $$
89
+ ${answer}\\ \\textrm{°C}
90
+ $$`,
91
+ randInitial: () => randint(0, 10),
92
+ randGrowth: () => randfloat(0.5, 1, 2),
93
+ },
94
+ {
95
+ instruction: (initial, growth) => `Emma est salariée. Son salaire net était
96
+ de $${initial.frenchify()}\\ €$ à son entrée dans l'entreprise,
97
+ et augmente de $${growth.frenchify()}$ € tous les ans.
98
+ Quel sera son salaire net (en €) quand elle aura $x$ années d'ancienneté ?`,
99
+ hint: `Quel calcul permet de trouver son salaire net pour $10$ années d'ancienneté ?
100
+
101
+ Inspire toi de ce calcul pour déterminer son salaire net pour $x$ années d'ancienneté.
102
+ `,
103
+ correction: (initial, growth, answer) => `Chaque année, son salaire net augmente de $${growth.frenchify()}$ €.
104
+ Au bout de $x$ années, son salaire net aura augmenté de $x\\times ${growth.frenchify()}$ €.
105
+
106
+ Au départ, son salaire net était de $${initial}$ €.
107
+
108
+ Pour $x$ années d'ancienneté, son salaire net sera donc de :
109
+
110
+ $$
111
+ ${answer}\\ \\textrm{€}
112
+ $$`,
113
+ randInitial: () => randint(12, 17) * 100,
114
+ randGrowth: () => randfloat(20, 50, 2),
115
+ },
116
+ ];
9
117
  const getPropositions = (n, { answer, ...identifiers }) => {
10
118
  const propositions = [];
11
119
  const { initial, growth } = identifiers;
@@ -20,54 +128,20 @@ const getAnswer = (identifiers) => {
20
128
  return add(multiply(identifiers.growth, new VariableNode("x")), identifiers.initial).toTex();
21
129
  };
22
130
  const getInstruction = (identifiers) => {
23
- const { phrase, initial, growth } = identifiers;
24
- switch (phrase) {
25
- case 0:
26
- return `On suppose qu'une plante, d'une hauteur initiale de
27
- $${initial}\\ \\textrm{cm}$, croît chaque jour de $${growth.frenchify()}\\ \\textrm{cm}$.
28
- Quelle est sa hauteur (en $\\textrm{cm}$) après $x$ jours ?`;
29
- case 1:
30
- default:
31
- return `Une compagnie de taxis propose un tarif qui inclut un
32
- montant fixe de $${initial}\\ €$ et un montant variable de $${growth.frenchify()}\\ €$
33
- par kilomètre parcouru.
34
- Quel est le prix payé (en $€$) pour $x \\ \\textrm{km}$ parcourus ?`;
35
- }
131
+ const { situationIndex, initial, growth } = identifiers;
132
+ const situation = situations[situationIndex];
133
+ return situation.instruction(initial, growth);
36
134
  };
37
135
  const getHint = (identifiers) => {
38
- const { phrase } = identifiers;
39
- if (phrase === 0) {
40
- return `Quel calcul permet de trouver la hauteur de la plante au bout de $10$ jours ?
41
-
42
- Inspire toi de ce calcul pour déterminer la hauteur de la plante au bout de $x$ jours.`;
43
- }
44
- return `Quel calcul permet de trouver le prix payé pour $10$ kilomètres parcourus ?
45
-
46
- Inspire toi de ce calcul pour déterminer le prix payé pour $x$ kilomètres parcourus.
47
- `;
136
+ const { situationIndex } = identifiers;
137
+ const situation = situations[situationIndex];
138
+ return situation.hint;
48
139
  };
49
140
  const getCorrection = (identifiers) => {
50
- const { growth, initial, phrase } = identifiers;
51
- if (phrase === 0) {
52
- return `Chaque jour, la plante gagne $${growth.frenchify()}\\ \\textrm{cm}$. Au bout de $x$ jours, la plante a donc gagné $x\\times ${growth.frenchify()}\\ \\textrm{cm}$.
53
-
54
- La hauteur initiale de la plante est de $${initial}\\ \\textrm{cm}$.
55
-
56
- Au bout de $x$ jours, la plante a donc une hauteur de :
57
-
58
- $$
59
- ${getAnswer(identifiers)}\\ \\textrm{cm}
60
- $$`;
61
- }
62
- return `Pour chaque kilomètre parcouru, le prix augmente de $${growth.frenchify()}\\ €$. Au bout de $x$ kilomètres, le prix augmente donc de $x\\times ${growth.frenchify()}\\ \\ €$.
63
-
64
- Le montant fixe initial du trajet est de $${initial}\\ €$.
65
-
66
- Pour $x$ kilomètres parcourus, le prix du trajet est donc de :
67
-
68
- $$
69
- ${getAnswer(identifiers)}\\ €
70
- $$`;
141
+ const { situationIndex, initial, growth } = identifiers;
142
+ const situation = situations[situationIndex];
143
+ const answer = getAnswer(identifiers);
144
+ return situation.correction(initial, growth, answer);
71
145
  };
72
146
  const isAnswerValid = (ans, { answer }) => {
73
147
  return parseAlgebraic(ans)
@@ -75,10 +149,11 @@ const isAnswerValid = (ans, { answer }) => {
75
149
  .equals(parseAlgebraic(answer).simplify());
76
150
  };
77
151
  const getAffineFromExerciseQuestion = () => {
78
- const phrase = randint(0, 2);
79
- const initial = randint(2, 20);
80
- const growth = randfloat(0, 4, 2, [0]);
81
- const identifiers = { phrase, initial, growth };
152
+ const situationIndex = randint(0, situations.length);
153
+ const situation = situations[situationIndex];
154
+ const initial = situation.randInitial();
155
+ const growth = situation.randGrowth();
156
+ const identifiers = { situationIndex, initial, growth };
82
157
  return getQuestionFromIdentifiers(identifiers);
83
158
  };
84
159
  const getQuestionFromIdentifiers = (identifiers) => {
@@ -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;
@@ -7,9 +7,10 @@ type ColorProps = {
7
7
  type FunctionProps = {
8
8
  fName: string;
9
9
  colorProps: ColorProps;
10
+ nodeIds: NodeIdentifiers;
11
+ isAnswer: boolean;
10
12
  };
11
13
  type Identifiers = {
12
- arrNodeIds: NodeIdentifiers[];
13
14
  arrFProps: FunctionProps[];
14
15
  isLinear: boolean;
15
16
  };
@@ -1 +1 @@
1
- {"version":3,"file":"recognizeAffineGraph.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/affines/recognizeAffineGraph.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAcT,MAAM,6BAA6B,CAAC;AAQrC,OAAO,EAEL,eAAe,EAChB,MAAM,qCAAqC,CAAC;AAc7C,KAAK,UAAU,GAAG;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAmBF,KAAK,aAAa,GAAG;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AA+IF,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,WAAW,CAgBtD,CAAC"}
1
+ {"version":3,"file":"recognizeAffineGraph.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/affines/recognizeAffineGraph.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAcT,MAAM,6BAA6B,CAAC;AASrC,OAAO,EAEL,eAAe,EAChB,MAAM,qCAAqC,CAAC;AAc7C,KAAK,UAAU,GAAG;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAmBF,KAAK,aAAa,GAAG;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAgKF,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,WAAW,CAgBtD,CAAC"}
@@ -19,10 +19,6 @@ const DISPLAY_PROPS = {
19
19
  yMax: +5,
20
20
  };
21
21
  const arrColorProps = [
22
- {
23
- strFrench: "rouge",
24
- hashRgb: red,
25
- },
26
22
  {
27
23
  strFrench: "bleu",
28
24
  hashRgb: blueDark,
@@ -31,6 +27,10 @@ const arrColorProps = [
31
27
  strFrench: "orange",
32
28
  hashRgb: orange,
33
29
  },
30
+ {
31
+ strFrench: "rouge",
32
+ hashRgb: red,
33
+ },
34
34
  ];
35
35
  const arrFName = ["f", "g", "h"];
36
36
  const getInstruction = (identifiers) => {
@@ -41,7 +41,7 @@ const getInstruction = (identifiers) => {
41
41
  Quelle fonction est ${isLinear ? "linéaire" : "affine"} ?`;
42
42
  };
43
43
  const getGGBOptions = (identifiers) => {
44
- const { arrNodeIds, arrFProps } = identifiers;
44
+ const { arrFProps } = identifiers;
45
45
  function createFunctionCommands(nodeIds, fName, color) {
46
46
  const nodeF = NodeConstructor.fromIdentifiers(nodeIds);
47
47
  const expr = nodeF.toMathString();
@@ -52,7 +52,7 @@ const getGGBOptions = (identifiers) => {
52
52
  `SetColor(${fName}, "${color}")`,
53
53
  ];
54
54
  }
55
- const commands = arrNodeIds.flatMap((_, i) => createFunctionCommands(arrNodeIds[i], arrFProps[i].fName, arrFProps[i].colorProps.hashRgb));
55
+ const commands = arrFProps.flatMap((fProps) => createFunctionCommands(fProps.nodeIds, fProps.fName, fProps.colorProps.hashRgb));
56
56
  const ggb = new GeogebraConstructor({
57
57
  commands,
58
58
  });
@@ -66,35 +66,52 @@ const getHint = () => {
66
66
  };
67
67
  const getCorrection = (identifiers) => {
68
68
  const { isLinear, arrFProps } = identifiers;
69
- const strFName = arrFProps[0].fName;
70
- const strColor = arrFProps[0].colorProps.strFrench;
69
+ const fPropsAnswer = arrFProps.find((fProps) => fProps.isAnswer);
70
+ const strFName = fPropsAnswer.fName;
71
+ const strColor = fPropsAnswer.colorProps.strFrench;
71
72
  return `Une fonction ${isLinear ? "linéaire" : "affine"} est représentée par une droite ${isLinear ? "passant par l'origine" : ""}.
72
73
  La seule droite ici est la courbe en ${strColor}.
73
74
  La fonction ${isLinear ? "linéaire" : "affine"} est donc $${strFName}$.`;
74
75
  };
75
76
  const getAnswer = (identifiers) => {
76
77
  const { arrFProps } = identifiers;
77
- return arrFProps[0].fName;
78
+ const fPropsAnswer = arrFProps.find((fProps) => fProps.isAnswer);
79
+ return fPropsAnswer.fName;
78
80
  };
79
81
  const getRecognizeAffineGraphQuestion = () => {
80
82
  const isLinear = coinFlip();
81
83
  const { xMin, xMax, yMin, yMax } = DISPLAY_PROPS;
82
- const arrNodeIds = [
83
- AffineConstructor.random({ min: -10, max: 10 }, { min: isLinear ? 0 : -10, max: isLinear ? 0 : 10 }, "x").toTree(),
84
- add(multiply(randint(-0.5, 0.5, [0]), exp("x")), randint(-5, 5)),
85
- (() => {
86
- const rootsPool = [...Array(xMax - xMin).keys()].map((i) => i + xMin);
87
- const roots = randomMany(rootsPool, 2).toSorted((i1, i2) => i1 - i2);
88
- const ySummit = randint(yMin, yMax, [0]);
89
- return TrinomConstructor.fromRootsAndSummitY(roots, ySummit).toTree();
90
- })(),
91
- ].map((node) => node.toIdentifiers());
92
- const arrFNameShuffled = shuffle(arrFName);
93
- const arrColorPropsShuffled = shuffle(arrColorProps);
94
- const arrFProps = arrFNameShuffled.map((_, i) => {
95
- return { fName: arrFName[i], colorProps: arrColorPropsShuffled[i] };
84
+ const arrItem = [
85
+ {
86
+ node: AffineConstructor.random({ min: -10, max: 10 }, { min: isLinear ? 0 : -10, max: isLinear ? 0 : 10 }, "x").toTree(),
87
+ isAnswer: true,
88
+ },
89
+ {
90
+ node: add(multiply(randint(-0.5, 0.5, [0]), exp("x")), randint(-5, 5)),
91
+ isAnswer: false,
92
+ },
93
+ {
94
+ node: (() => {
95
+ const rootsPool = [...Array(xMax - xMin).keys()].map((i) => i + xMin);
96
+ const roots = randomMany(rootsPool, 2).toSorted((i1, i2) => i1 - i2);
97
+ const ySummit = randint(yMin, yMax, [0]);
98
+ return TrinomConstructor.fromRootsAndSummitY(roots, ySummit).toTree();
99
+ })(),
100
+ isAnswer: false,
101
+ },
102
+ ];
103
+ const arrFProps = shuffle(arrItem).map((item, i) => {
104
+ return {
105
+ fName: arrFName[i],
106
+ colorProps: arrColorProps[i],
107
+ nodeIds: item.node.toIdentifiers(),
108
+ isAnswer: item.isAnswer,
109
+ };
96
110
  });
97
- const identifiers = { arrNodeIds, arrFProps, isLinear };
111
+ const identifiers = {
112
+ arrFProps,
113
+ isLinear,
114
+ };
98
115
  return getQuestionFromIdentifiers(identifiers);
99
116
  };
100
117
  const getQuestionFromIdentifiers = (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"}