math-exercises 3.0.131 → 3.0.133

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 (109) hide show
  1. package/lib/exercises/exercise.d.ts +37 -30
  2. package/lib/exercises/exercise.d.ts.map +1 -1
  3. package/lib/exercises/math/calcul/mentalCaluls/mentalProgramSolve.d.ts +2 -2
  4. package/lib/exercises/math/calcul/mentalCaluls/mentalProgramSolve.d.ts.map +1 -1
  5. package/lib/exercises/math/calcul/mentalCaluls/mentalProgramSolve.js +44 -40
  6. package/lib/exercises/math/calcul/ordering/compareA10N.d.ts +1 -1
  7. package/lib/exercises/math/calcul/ordering/compareA10N.d.ts.map +1 -1
  8. package/lib/exercises/math/calcul/ordering/compareA10N.js +15 -10
  9. package/lib/exercises/math/calcul/ordering/compareFracABWithFracAPlusCBPlusC.d.ts.map +1 -1
  10. package/lib/exercises/math/calcul/ordering/compareFracABWithFracAPlusCBPlusC.js +0 -1
  11. package/lib/exercises/math/calcul/ordering/compareFracAndDec.d.ts +1 -1
  12. package/lib/exercises/math/calcul/ordering/compareFracAndDec.js +1 -1
  13. package/lib/exercises/math/calcul/proportionality/findCoeffInProportionalTableNonIntegers.js +1 -1
  14. package/lib/exercises/math/calcul/proportionality/isTableProportionalNonInteger.d.ts.map +1 -1
  15. package/lib/exercises/math/calcul/proportionality/isTableProportionalNonInteger.js +2 -0
  16. package/lib/exercises/math/calcul/rounding/estimatePow10NPlusPow10MinusN.d.ts.map +1 -1
  17. package/lib/exercises/math/calcul/rounding/estimatePow10NPlusPow10MinusN.js +8 -6
  18. package/lib/exercises/math/calcul/rounding/rounding.d.ts +1 -1
  19. package/lib/exercises/math/calcul/rounding/rounding.d.ts.map +1 -1
  20. package/lib/exercises/math/calcul/rounding/rounding.js +7 -6
  21. package/lib/exercises/math/calculLitteral/equation/equationFromProblem.d.ts.map +1 -1
  22. package/lib/exercises/math/calculLitteral/equation/equationFromProblem.js +8 -9
  23. package/lib/exercises/math/calculLitteral/simplifying/compareATimes0.d.ts.map +1 -1
  24. package/lib/exercises/math/calculLitteral/simplifying/compareATimes0.js +4 -4
  25. package/lib/exercises/math/calculLitteral/writing/writeLitExpFromFrenchExp.d.ts.map +1 -1
  26. package/lib/exercises/math/calculLitteral/writing/writeLitExpFromFrenchExp.js +15 -60
  27. package/lib/exercises/math/conversion/kmPerMinToKmPerHourConversion.js +14 -10
  28. package/lib/exercises/math/conversion/lengthConversion.d.ts.map +1 -1
  29. package/lib/exercises/math/conversion/lengthConversion.js +1 -0
  30. package/lib/exercises/math/conversion/prefixToNumber.d.ts +0 -2
  31. package/lib/exercises/math/conversion/prefixToNumber.d.ts.map +1 -1
  32. package/lib/exercises/math/conversion/prefixToNumber.js +31 -24
  33. package/lib/exercises/math/conversion/secondsToHours.js +1 -1
  34. package/lib/exercises/math/functions/affines/drawAffineFromPointAndLeadingCoeff.js +2 -2
  35. package/lib/exercises/math/functions/affines/drawAffineFromProgCalc.d.ts +1 -1
  36. package/lib/exercises/math/functions/affines/drawAffineFromProgCalc.d.ts.map +1 -1
  37. package/lib/exercises/math/functions/affines/drawAffineFromProgCalc.js +4 -5
  38. package/lib/exercises/math/functions/affines/leadingCoefficient.js +1 -1
  39. package/lib/exercises/math/geometry/angles/anglesUsingIsParallel.d.ts +1 -1
  40. package/lib/exercises/math/geometry/angles/anglesUsingIsParallel.d.ts.map +1 -1
  41. package/lib/exercises/math/geometry/angles/anglesUsingIsParallel.js +10 -11
  42. package/lib/exercises/math/geometry/angles/isParallelUsingAngles.d.ts +1 -1
  43. package/lib/exercises/math/geometry/angles/isParallelUsingAngles.d.ts.map +1 -1
  44. package/lib/exercises/math/geometry/angles/isParallelUsingAngles.js +8 -8
  45. package/lib/exercises/math/geometry/cartesian/index.d.ts +1 -0
  46. package/lib/exercises/math/geometry/cartesian/index.d.ts.map +1 -1
  47. package/lib/exercises/math/geometry/cartesian/index.js +1 -0
  48. package/lib/exercises/math/geometry/cartesian/placeAbscissOnSemiLine.d.ts +6 -9
  49. package/lib/exercises/math/geometry/cartesian/placeAbscissOnSemiLine.d.ts.map +1 -1
  50. package/lib/exercises/math/geometry/cartesian/placeAbscissOnSemiLine.js +60 -137
  51. package/lib/exercises/math/geometry/cartesian/placeAbscissOnSemiLineV2.d.ts +16 -0
  52. package/lib/exercises/math/geometry/cartesian/placeAbscissOnSemiLineV2.d.ts.map +1 -0
  53. package/lib/exercises/math/geometry/cartesian/placeAbscissOnSemiLineV2.js +213 -0
  54. package/lib/exercises/math/percent/evolutions/globalPercent.d.ts +4 -1
  55. package/lib/exercises/math/percent/evolutions/globalPercent.d.ts.map +1 -1
  56. package/lib/exercises/math/percent/evolutions/globalPercent.js +37 -21
  57. package/lib/exercises/math/percent/findProportion.d.ts.map +1 -1
  58. package/lib/exercises/math/percent/findProportion.js +24 -26
  59. package/lib/exercises/math/percent/percentToDecimal.d.ts +4 -1
  60. package/lib/exercises/math/percent/percentToDecimal.d.ts.map +1 -1
  61. package/lib/exercises/math/percent/percentToDecimal.js +55 -35
  62. package/lib/exercises/math/powers/calculateNegativePower.d.ts +1 -1
  63. package/lib/exercises/math/powers/calculateNegativePower.d.ts.map +1 -1
  64. package/lib/exercises/math/powers/calculateNegativePower.js +17 -10
  65. package/lib/exercises/math/probaStat/basicProbas/possibleValuesForProba.js +2 -2
  66. package/lib/exercises/math/probaStat/basicStats/calculateFrequencyInList.d.ts +5 -1
  67. package/lib/exercises/math/probaStat/basicStats/calculateFrequencyInList.d.ts.map +1 -1
  68. package/lib/exercises/math/probaStat/basicStats/calculateFrequencyInList.js +76 -12
  69. package/lib/exercises/math/probaStat/conditionalProbaWriteFromFrench.js +7 -7
  70. package/lib/exercises/math/probaStat/probaAsSumOfProbas.d.ts +2 -3
  71. package/lib/exercises/math/probaStat/probaAsSumOfProbas.d.ts.map +1 -1
  72. package/lib/exercises/math/probaStat/probaAsSumOfProbas.js +60 -95
  73. package/lib/exercises/math/probaStat/probaFromTableWithContext.d.ts +12 -5
  74. package/lib/exercises/math/probaStat/probaFromTableWithContext.d.ts.map +1 -1
  75. package/lib/exercises/math/probaStat/probaFromTableWithContext.js +354 -94
  76. package/lib/exercises/math/probaStat/stats1var/medianWithList.d.ts +4 -1
  77. package/lib/exercises/math/probaStat/stats1var/medianWithList.d.ts.map +1 -1
  78. package/lib/exercises/math/probaStat/stats1var/medianWithList.js +43 -23
  79. package/lib/exercises/math/probaStat/stats1var/plausibilityOfAverage.d.ts.map +1 -1
  80. package/lib/exercises/math/probaStat/stats1var/plausibilityOfAverage.js +70 -23
  81. package/lib/exercises/math/probaStat/stats1var/quartilesList.d.ts +1 -1
  82. package/lib/exercises/math/probaStat/stats1var/quartilesList.d.ts.map +1 -1
  83. package/lib/exercises/math/probaStat/stats1var/quartilesList.js +4 -4
  84. package/lib/exercises/pc/index.d.ts +0 -1
  85. package/lib/exercises/pc/index.d.ts.map +1 -1
  86. package/lib/exercises/pc/index.js +0 -1
  87. package/lib/exercises/pc/motion/averageSpeed.d.ts +0 -2
  88. package/lib/exercises/pc/motion/averageSpeed.d.ts.map +1 -1
  89. package/lib/exercises/pc/motion/averageSpeed.js +40 -45
  90. package/lib/exercises/pc/optics/lensFormula.d.ts +1 -2
  91. package/lib/exercises/pc/optics/lensFormula.d.ts.map +1 -1
  92. package/lib/exercises/pc/optics/lensFormula.js +7 -10
  93. package/lib/exercises/pc/weight/calculateWeight.d.ts +1 -3
  94. package/lib/exercises/pc/weight/calculateWeight.d.ts.map +1 -1
  95. package/lib/exercises/pc/weight/calculateWeight.js +38 -30
  96. package/lib/index.d.ts +932 -948
  97. package/lib/index.d.ts.map +1 -1
  98. package/lib/math/progCalc/progCalc.d.ts +2 -2
  99. package/lib/math/progCalc/progCalc.d.ts.map +1 -1
  100. package/lib/math/progCalc/progCalc.js +4 -11
  101. package/lib/playgroundUtils.d.ts +3 -0
  102. package/lib/playgroundUtils.d.ts.map +1 -0
  103. package/lib/playgroundUtils.js +13 -0
  104. package/lib/server.js +121 -0
  105. package/lib/tests/exoTest.d.ts.map +1 -1
  106. package/lib/tests/exoTest.js +13 -0
  107. package/lib/types/keyIds.d.ts +1 -1
  108. package/lib/types/keyIds.d.ts.map +1 -1
  109. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { randint } from "../../../../math/utils/random/randint.js";
2
- import { addValidProp, propWhile, tryToAddWrongProp, } from "../../../exercise.js";
2
+ import { GeneratorOptionTarget, GeneratorOptionType, addValidProp, propWhile, tryToAddWrongProp, } from "../../../exercise.js";
3
3
  import { getDistinctQuestions } from "../../../utils/getDistinctQuestions.js";
4
4
  import { shuffle } from "../../../../utils/alea/shuffle.js";
5
5
  import { round } from "../../../../math/utils/round.js";
@@ -48,8 +48,26 @@ $$
48
48
  Le taux d'évolution global est donc de $${answer}$.
49
49
  `;
50
50
  };
51
- const getGlobalPercentQuestion = () => {
52
- const indice = randint(2, 4);
51
+ const getPropositions = (n, { answer }) => {
52
+ const propositions = [];
53
+ addValidProp(propositions, answer);
54
+ propWhile(propositions, n, () => {
55
+ let wrongAnswer = Number(answer.replace(",", ".").replace(`\\%`, ""));
56
+ const deviation = Math.random() < 0.5 ? -1 : 1;
57
+ const percentDeviation = Math.random() * 20 + 1;
58
+ wrongAnswer += deviation * percentDeviation;
59
+ wrongAnswer = round(wrongAnswer, 2);
60
+ tryToAddWrongProp(propositions, `${(wrongAnswer + "").replace(".", ",")} \\%`);
61
+ });
62
+ return shuffle(propositions);
63
+ };
64
+ const isAnswerValid = (ans, { answer }) => {
65
+ const parsed = percentParser(ans);
66
+ return parsed === answer.replace("+", "");
67
+ };
68
+ const getGlobalPercentQuestion = (optsIn) => {
69
+ const opts = optsIn ?? optsDefault;
70
+ const indice = Number(opts.nbEvos);
53
71
  const evolutions = [];
54
72
  for (let i = 0; i < indice; i++) {
55
73
  const randPercent = randint(1, 50);
@@ -59,7 +77,7 @@ const getGlobalPercentQuestion = () => {
59
77
  const identifiers = { evolutions };
60
78
  return getQuestionFromIdentifiers(identifiers);
61
79
  };
62
- const getQuestionFromIdentifiers = (identifiers) => {
80
+ const getQuestionFromIdentifiers = (identifiers, opts) => {
63
81
  const question = {
64
82
  instruction: getInstruction(identifiers),
65
83
  answer: getAnswer(identifiers),
@@ -68,32 +86,30 @@ const getQuestionFromIdentifiers = (identifiers) => {
68
86
  identifiers,
69
87
  hint: getHint(identifiers),
70
88
  correction: getCorrection(identifiers),
89
+ options: opts,
71
90
  };
72
91
  return question;
73
92
  };
74
- const getPropositions = (n, { answer }) => {
75
- const propositions = [];
76
- addValidProp(propositions, answer);
77
- propWhile(propositions, n, () => {
78
- let wrongAnswer = Number(answer.replace(",", ".").replace(`\\%`, ""));
79
- const deviation = Math.random() < 0.5 ? -1 : 1;
80
- const percentDeviation = Math.random() * 20 + 1;
81
- wrongAnswer += deviation * percentDeviation;
82
- wrongAnswer = round(wrongAnswer, 2);
83
- tryToAddWrongProp(propositions, `${(wrongAnswer + "").replace(".", ",")} \\%`);
84
- });
85
- return shuffle(propositions);
86
- };
87
- const isAnswerValid = (ans, { answer }) => {
88
- const parsed = percentParser(ans);
89
- return parsed === answer.replace("+", "");
93
+ const optsDefault = {
94
+ nbEvos: "2",
90
95
  };
96
+ const options = [
97
+ {
98
+ id: "nbEvos",
99
+ label: "Nombre d'évolutions successives",
100
+ target: GeneratorOptionTarget.generation,
101
+ type: GeneratorOptionType.select,
102
+ values: ["2", "3", "4"],
103
+ defaultValue: optsDefault.nbEvos,
104
+ },
105
+ ];
91
106
  export const globalPercent = {
92
107
  id: "globalPercent",
93
108
  connector: "=",
94
109
  label: "Calculer un taux d'évolution global à partir de taux d'évolution successifs",
95
110
  isSingleStep: false,
96
- generator: (nb) => getDistinctQuestions(getGlobalPercentQuestion, nb),
111
+ generator: (nb, opts) => getDistinctQuestions(() => getGlobalPercentQuestion(opts), nb),
112
+ options,
97
113
  qcmTimer: 60,
98
114
  freeTimer: 60,
99
115
  getPropositions,
@@ -1 +1 @@
1
- {"version":3,"file":"findProportion.d.ts","sourceRoot":"","sources":["../../../../src/exercises/math/percent/findProportion.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAeT,MAAM,6BAA6B,CAAC;AAarC,KAAK,WAAW,GAAG;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAgOF,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,WAAW,CAehD,CAAC"}
1
+ {"version":3,"file":"findProportion.d.ts","sourceRoot":"","sources":["../../../../src/exercises/math/percent/findProportion.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAeT,MAAM,6BAA6B,CAAC;AAarC,KAAK,WAAW,GAAG;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AA4NF,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,WAAW,CAehD,CAAC"}
@@ -6,10 +6,10 @@ import { round } from "../../../math/utils/round.js";
6
6
  import { frac } from "../../../tree/nodes/operators/fractionNode.js";
7
7
  import { multiply } from "../../../tree/nodes/operators/multiplyNode.js";
8
8
  import { substract } from "../../../tree/nodes/operators/substractNode.js";
9
- import { parseAlgebraic } from "../../../tree/parsers/latexParser.js";
9
+ import { percentParser } from "../../../tree/parsers/percentParser.js";
10
+ import { valueParser } from "../../../tree/parsers/valueParser.js";
10
11
  import { random } from "../../../utils/alea/random.js";
11
12
  import { handleVEAError } from "../../../utils/errors/handleVEAError.js";
12
- import { alignTex } from "../../../utils/latex/alignTex.js";
13
13
  const situations = [
14
14
  {
15
15
  instruction: (total, lefties) => `${random([
@@ -114,14 +114,10 @@ const getHint = (identifiers) => {
114
114
  const situation = situations[indexSituation];
115
115
  return `${situation.hint}
116
116
 
117
- Rappel :
117
+ Pour transformer un nombre décimal en pourcentage, on le multiplie par $100$. Par exemple,
118
118
 
119
119
  $$
120
- 2\\% = 0,02
121
- $$
122
-
123
- $$
124
- 2,01\\% = 0,0201
120
+ 0,345 = 34,5\\%
125
121
  $$
126
122
 
127
123
  `;
@@ -135,16 +131,9 @@ const getCorrection = (identifiers) => {
135
131
  const middleSymbol = isEqual ? "=" : "\\approx";
136
132
  return `On a :
137
133
 
138
- ${alignTex([
139
- [`${fractionNode.toTex()}`, middleSymbol, `${roundedProportion.frenchify()}`],
140
- [
141
- "",
142
- middleSymbol,
143
- `${roundedProportion.frenchify()} \\times 100 \\times \\frac{1}{100}`,
144
- ],
145
- ["", middleSymbol, `${roundedProportion.frenchify()} \\times 100 \\ \\%`],
146
- ["", middleSymbol, `${getAnswer(identifiers)}`],
147
- ])}
134
+ $$
135
+ ${fractionNode.toTex()} ${middleSymbol} ${roundedProportion.frenchify()}
136
+ $$
148
137
 
149
138
  ${situation.correction} $${getAnswer(identifiers)}$.`;
150
139
  };
@@ -163,14 +152,19 @@ const getPropositions = (n, { answer, total, lefties }) => {
163
152
  });
164
153
  return shuffleProps(propositions, n);
165
154
  };
166
- const isAnswerValid = (ans, { answer, ...identifiers }) => {
167
- const { lefties, total } = identifiers;
155
+ const isAnswerValid = (ans, { answer, lefties, total }) => {
168
156
  try {
169
- const percentNode = frac(1, 100);
170
- const refinedAns = ans.replaceAll("\\%", `({${percentNode.toTex()}})`);
171
- const nodeAns = parseAlgebraic(refinedAns);
172
- const nodeAnswer = round(lefties / total, 4);
173
- return substract(nodeAns, nodeAnswer).simplify().evaluate() === 0;
157
+ if (ans.includes("\\%")) {
158
+ const parsed = percentParser(ans);
159
+ return parsed === answer;
160
+ }
161
+ else {
162
+ const answerValue = round(lefties / total, 4);
163
+ const studentAns = valueParser(ans);
164
+ if (!studentAns)
165
+ return false;
166
+ return answerValue === studentAns;
167
+ }
174
168
  }
175
169
  catch (err) {
176
170
  return handleVEAError(err);
@@ -181,7 +175,11 @@ const getFindProportionQuestion = () => {
181
175
  const situation = situations[indexSituation];
182
176
  const total = situation.randTotal();
183
177
  const lefties = round(randfloat(0.1, 0.9) * total, 0);
184
- return getQuestionFromIdentifiers({ indexSituation, total, lefties });
178
+ return getQuestionFromIdentifiers({
179
+ indexSituation,
180
+ total,
181
+ lefties,
182
+ });
185
183
  };
186
184
  const getQuestionFromIdentifiers = (identifiers) => {
187
185
  const question = {
@@ -3,6 +3,9 @@ type Identifiers = {
3
3
  isPercentToDecimal: boolean;
4
4
  nb: number;
5
5
  };
6
- export declare const percentToDecimal: Exercise<Identifiers>;
6
+ type Options = {
7
+ conversionType: string;
8
+ };
9
+ export declare const percentToDecimal: Exercise<Identifiers, Options>;
7
10
  export {};
8
11
  //# sourceMappingURL=percentToDecimal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"percentToDecimal.d.ts","sourceRoot":"","sources":["../../../../src/exercises/math/percent/percentToDecimal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAgBT,MAAM,6BAA6B,CAAC;AAgBrC,KAAK,WAAW,GAAG;IACjB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AA8IF,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,WAAW,CAclD,CAAC"}
1
+ {"version":3,"file":"percentToDecimal.d.ts","sourceRoot":"","sources":["../../../../src/exercises/math/percent/percentToDecimal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAmBT,MAAM,6BAA6B,CAAC;AAiBrC,KAAK,WAAW,GAAG;IACjB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AA4JF,KAAK,OAAO,GAAG;IACb,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAsBF,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAe3D,CAAC"}
@@ -1,4 +1,4 @@
1
- import { addValidProp, propWhile, shuffleProps, tryToAddWrongProp, } from "../../../exercises/exercise.js";
1
+ import { GeneratorOptionTarget, GeneratorOptionType, addValidProp, propWhile, shuffleProps, tryToAddWrongProp, } from "../../../exercises/exercise.js";
2
2
  import { getDistinctQuestions } from "../../../exercises/utils/getDistinctQuestions.js";
3
3
  import { Decimal, DecimalConstructor, } from "../../../math/numbers/decimals/decimal.js";
4
4
  import { Integer, IntegerConstructor, } from "../../../math/numbers/integer/integer.js";
@@ -7,6 +7,7 @@ import { round } from "../../../math/utils/round.js";
7
7
  import { numberParser } from "../../../tree/parsers/numberParser.js";
8
8
  import { coinFlip } from "../../../utils/alea/coinFlip.js";
9
9
  import { probaFlip } from "../../../utils/alea/probaFlip.js";
10
+ import { random } from "../../../utils/alea/random.js";
10
11
  const getAnswer = ({ nb, isPercentToDecimal }) => {
11
12
  const dec = new Decimal(nb);
12
13
  const tex = dec.toTree().toTex();
@@ -48,39 +49,6 @@ En effet, on a bien $${answer} = \\frac{${answer.replace("\\%", "")}}{100} = ${n
48
49
  const getKeys = () => {
49
50
  return ["percent"];
50
51
  };
51
- const getPercentToDecimalQuestion = () => {
52
- const isPercentToDecimal = coinFlip();
53
- const isNatural = coinFlip();
54
- const percentNb = probaFlip(0.3)
55
- ? isNatural
56
- ? new Integer(IntegerConstructor.random(1, [0]))
57
- : DecimalConstructor.random(0, 10)
58
- : coinFlip()
59
- ? isNatural
60
- ? new Integer(IntegerConstructor.random(2))
61
- : DecimalConstructor.random(10, 100)
62
- : isNatural
63
- ? new Integer(IntegerConstructor.random(3))
64
- : DecimalConstructor.random(100, 200);
65
- const nb = percentNb.times(0.01);
66
- const identifiers = {
67
- isPercentToDecimal,
68
- nb: round(nb.value, 10),
69
- };
70
- return getQuestionFromIdentifiers(identifiers);
71
- };
72
- const getQuestionFromIdentifiers = (identifiers) => {
73
- const question = {
74
- answer: getAnswer(identifiers),
75
- instruction: getInstruction(identifiers),
76
- keys: getKeys(identifiers),
77
- answerFormat: "tex",
78
- identifiers,
79
- hint: getHint(identifiers),
80
- correction: getCorrection(identifiers),
81
- };
82
- return question;
83
- };
84
52
  const getPropositions = (n, { answer, isPercentToDecimal, nb }) => {
85
53
  const propositions = [];
86
54
  addValidProp(propositions, answer);
@@ -113,12 +81,64 @@ const isAnswerValid = (ans, { answer, isPercentToDecimal }) => {
113
81
  return parsed + "\\%" === answer;
114
82
  }
115
83
  };
84
+ const getPercentToDecimalQuestion = (optsIn) => {
85
+ const arrayedOptions = optsIn ?? optsDefault;
86
+ const opts = {
87
+ conversionType: random(arrayedOptions.conversionType),
88
+ };
89
+ const isPercentToDecimal = opts.conversionType === "Pourcentage vers Décimal";
90
+ const isNatural = coinFlip();
91
+ const percentNb = probaFlip(0.3)
92
+ ? isNatural
93
+ ? new Integer(IntegerConstructor.random(1, [0]))
94
+ : DecimalConstructor.random(0, 10)
95
+ : coinFlip()
96
+ ? isNatural
97
+ ? new Integer(IntegerConstructor.random(2))
98
+ : DecimalConstructor.random(10, 100)
99
+ : isNatural
100
+ ? new Integer(IntegerConstructor.random(3))
101
+ : DecimalConstructor.random(100, 200);
102
+ const nb = percentNb.times(0.01);
103
+ const identifiers = {
104
+ isPercentToDecimal,
105
+ nb: round(nb.value, 10),
106
+ };
107
+ return getQuestionFromIdentifiers(identifiers, opts);
108
+ };
109
+ const getQuestionFromIdentifiers = (identifiers, opts) => {
110
+ const question = {
111
+ answer: getAnswer(identifiers),
112
+ instruction: getInstruction(identifiers),
113
+ keys: getKeys(identifiers),
114
+ answerFormat: "tex",
115
+ identifiers,
116
+ hint: getHint(identifiers),
117
+ correction: getCorrection(identifiers),
118
+ options: opts,
119
+ };
120
+ return question;
121
+ };
122
+ const optsDefault = {
123
+ conversionType: ["Pourcentage vers Décimal", "Décimal vers Pourcentage"],
124
+ };
125
+ const options = [
126
+ {
127
+ id: "conversionType",
128
+ label: "Type de conversion",
129
+ target: GeneratorOptionTarget.generation,
130
+ type: GeneratorOptionType.multiselect,
131
+ values: ["Pourcentage vers Décimal", "Décimal vers Pourcentage"],
132
+ defaultValue: optsDefault.conversionType,
133
+ },
134
+ ];
116
135
  export const percentToDecimal = {
117
136
  id: "percentToDecimal",
118
137
  connector: "=",
119
138
  label: "Écrire un pourcentage sous forme décimale et vice-versa",
120
139
  isSingleStep: true,
121
- generator: (nb) => getDistinctQuestions(getPercentToDecimalQuestion, nb),
140
+ generator: (nb, opts) => getDistinctQuestions(() => getPercentToDecimalQuestion(opts), nb),
141
+ options,
122
142
  qcmTimer: 60,
123
143
  freeTimer: 60,
124
144
  getPropositions,
@@ -2,7 +2,7 @@ import { Exercise } from "../../../exercises/exercise.js";
2
2
  type Identifiers = {
3
3
  int: number;
4
4
  power: number;
5
- opts: Options;
5
+ isPowerAllowed: boolean;
6
6
  };
7
7
  type Options = {
8
8
  isPowerAllowed: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"calculateNegativePower.d.ts","sourceRoot":"","sources":["../../../../src/exercises/math/powers/calculateNegativePower.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAkBT,MAAM,6BAA6B,CAAC;AA0CrC,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AA4JF,KAAK,OAAO,GAAG;IACb,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAeF,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAgBjE,CAAC"}
1
+ {"version":3,"file":"calculateNegativePower.d.ts","sourceRoot":"","sources":["../../../../src/exercises/math/powers/calculateNegativePower.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAmBT,MAAM,6BAA6B,CAAC;AA0CrC,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AA4KF,KAAK,OAAO,GAAG;IACb,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAcF,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAiBjE,CAAC"}
@@ -25,8 +25,14 @@ const isNodeContainingOperatorId = (node, opId) => {
25
25
  return false;
26
26
  }
27
27
  };
28
+ const rebuildIdentifiers = (oldIds) => {
29
+ const newIds = Object.assign({}, oldIds, {
30
+ isPowerAllowed: true,
31
+ });
32
+ return newIds;
33
+ };
28
34
  const getInstruction = (identifiers) => {
29
- const { int, power, opts } = identifiers;
35
+ const { int, power, isPowerAllowed } = identifiers;
30
36
  const statement = new PowerNode(new NumberNode(int), new NumberNode(power)).toTex();
31
37
  return `Calculer et donner le résultat sous la forme d'une fraction ou d'un entier :
32
38
 
@@ -34,14 +40,14 @@ $$
34
40
  ${statement}
35
41
  $$
36
42
 
37
- ${opts.isPowerAllowed
43
+ ${isPowerAllowed
38
44
  ? `La réponse pourra comporter un exposant.`
39
45
  : `La réponse ne devra comporter aucun exposant.`}`;
40
46
  };
41
47
  const getAnswer = (identifiers) => {
42
- const { int, power, opts } = identifiers;
48
+ const { int, power, isPowerAllowed } = identifiers;
43
49
  const powerNode = new PowerNode(int.toTree(), Math.abs(power).toTree());
44
- const fraction = frac(1, opts.isPowerAllowed ? powerNode : powerNode.evaluate().toTree());
50
+ const fraction = frac(1, isPowerAllowed ? powerNode : powerNode.evaluate().toTree());
45
51
  const answer = fraction.simplify();
46
52
  return answer.toTex();
47
53
  };
@@ -53,7 +59,7 @@ a^{-x} = \\frac{1}{a^x}
53
59
  $$`;
54
60
  };
55
61
  const getCorrection = (identifiers) => {
56
- const { int, power, opts } = identifiers;
62
+ const { int, power, isPowerAllowed } = identifiers;
57
63
  const statement = new PowerNode(new NumberNode(int), new NumberNode(power)).toTex();
58
64
  const fraction = frac(1, new PowerNode(int.toTree(), Math.abs(power).toTree()));
59
65
  const simplificationTex = fraction.toSimplificationTex();
@@ -64,7 +70,7 @@ ${statement} = ${simplificationTex}
64
70
  $$
65
71
 
66
72
  ${(() => {
67
- if (!opts.isPowerAllowed) {
73
+ if (!isPowerAllowed) {
68
74
  const fractionNoPower = frac(1, new PowerNode(int.toTree(), Math.abs(power).toTree()).evaluate().toTree());
69
75
  const texNoPower = fractionNoPower.toTex();
70
76
  return !simplificationTex.includes(texNoPower)
@@ -105,12 +111,12 @@ const getPropositions = (n, { answer, int, power }) => {
105
111
  });
106
112
  return shuffleProps(propositions, n);
107
113
  };
108
- const isAnswerValid = (ans, { answer, opts }) => {
114
+ const isAnswerValid = (ans, { answer, isPowerAllowed }) => {
109
115
  try {
110
116
  const parsed = parseAlgebraic(ans);
111
117
  if (!isNumberNode(parsed) &&
112
118
  !(isFractionNode(parsed) &&
113
- (opts.isPowerAllowed ||
119
+ (isPowerAllowed ||
114
120
  !isNodeContainingOperatorId(parsed, OperatorIds.power)))) {
115
121
  return false;
116
122
  }
@@ -122,9 +128,10 @@ const isAnswerValid = (ans, { answer, opts }) => {
122
128
  };
123
129
  const getCalculatePowerQuestion = (optsIn) => {
124
130
  const opts = optsIn ?? optsDefault;
131
+ const isPowerAllowed = opts.isPowerAllowed;
125
132
  const int = randint(1, 11);
126
133
  const power = randint(-5, 0);
127
- const identifiers = { int, power, opts };
134
+ const identifiers = { int, power, isPowerAllowed };
128
135
  return getQuestionFromIdentifiers(identifiers, opts);
129
136
  };
130
137
  const getQuestionFromIdentifiers = (identifiers, opts) => {
@@ -149,7 +156,6 @@ const options = [
149
156
  label: "Exposant accepté dans la réponse",
150
157
  target: GeneratorOptionTarget.generation,
151
158
  type: GeneratorOptionType.checkbox,
152
- values: [true, false],
153
159
  defaultValue: optsDefault.isPowerAllowed,
154
160
  },
155
161
  ];
@@ -168,4 +174,5 @@ export const calculateNegativePower = {
168
174
  getQuestionFromIdentifiers,
169
175
  hasHintAndCorrection: true,
170
176
  shouldHaveCalculator: false,
177
+ rebuildIdentifiers: rebuildIdentifiers,
171
178
  };
@@ -103,7 +103,7 @@ const createRandomNode = (numberType, isPossibleProba) => {
103
103
  case "Fraction": {
104
104
  if (probaFlip(0.7)) {
105
105
  const num = randint(0, 10_000);
106
- const den = randint(num, 20_000);
106
+ const den = randint(num, 20_000, [0]);
107
107
  return frac(num, den);
108
108
  }
109
109
  else {
@@ -145,7 +145,7 @@ const createRandomNode = (numberType, isPossibleProba) => {
145
145
  const num = coinFlip()
146
146
  ? randint(10_000, 20_000)
147
147
  : randint(-20_000, -10_000);
148
- const den = randint(0, abs(num).evaluate());
148
+ const den = randint(1, abs(num).evaluate());
149
149
  return frac(num, den);
150
150
  }
151
151
  else {
@@ -2,7 +2,11 @@ import { Exercise } from "../../../../exercises/exercise.js";
2
2
  type Identifiers = {
3
3
  values: number[];
4
4
  target: number;
5
+ allowedAnsType: string[];
5
6
  };
6
- export declare const calculateFrequencyInList: Exercise<Identifiers>;
7
+ type Options = {
8
+ allowedAnsType: string[];
9
+ };
10
+ export declare const calculateFrequencyInList: Exercise<Identifiers, Options>;
7
11
  export {};
8
12
  //# sourceMappingURL=calculateFrequencyInList.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"calculateFrequencyInList.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/probaStat/basicStats/calculateFrequencyInList.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAeT,MAAM,6BAA6B,CAAC;AASrC,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAoHF,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,WAAW,CAc1D,CAAC"}
1
+ {"version":3,"file":"calculateFrequencyInList.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/probaStat/basicStats/calculateFrequencyInList.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAmBT,MAAM,6BAA6B,CAAC;AAYrC,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC;AA8LF,KAAK,OAAO,GAAG;IACb,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC;AAsBF,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAgBnE,CAAC"}
@@ -1,11 +1,19 @@
1
- import { addValidProp, shuffleProps, tryToAddWrongProp, propWhile, } from "../../../../exercises/exercise.js";
1
+ import { addValidProp, shuffleProps, tryToAddWrongProp, propWhile, GeneratorOptionTarget, GeneratorOptionType, } from "../../../../exercises/exercise.js";
2
2
  import { getDistinctQuestions } from "../../../../exercises/utils/getDistinctQuestions.js";
3
3
  import { RationalConstructor } from "../../../../math/numbers/rationals/rational.js";
4
4
  import { randint } from "../../../../math/utils/random/randint.js";
5
+ import { round } from "../../../../math/utils/round.js";
5
6
  import { frac } from "../../../../tree/nodes/operators/fractionNode.js";
7
+ import { substract } from "../../../../tree/nodes/operators/substractNode.js";
6
8
  import { parseAlgebraic } from "../../../../tree/parsers/latexParser.js";
7
9
  import { probaFlip } from "../../../../utils/alea/probaFlip.js";
8
10
  import { handleVEAError } from "../../../../utils/errors/handleVEAError.js";
11
+ const rebuildIdentifiers = (oldIds) => {
12
+ const newIds = Object.assign({}, oldIds, {
13
+ allowedAnsType: ["exacte", "arrondie à 2 décimales"],
14
+ });
15
+ return newIds;
16
+ };
9
17
  const getPropositions = (n, { answer, ...identifiers }) => {
10
18
  const propositions = [];
11
19
  addValidProp(propositions, answer);
@@ -17,13 +25,17 @@ const getPropositions = (n, { answer, ...identifiers }) => {
17
25
  });
18
26
  return shuffleProps(propositions, n);
19
27
  };
20
- const getAnswer = (identifiers) => {
21
- const { target, values } = identifiers;
28
+ const getAnswerNode = (identifiers) => {
29
+ const { target, values, allowedAnsType } = identifiers;
22
30
  const nb = values.filter((v) => v === target).length;
23
- return frac(nb, values.length).simplify({ fractionsToDecimal: true }).toTex();
31
+ const exactNode = frac(nb, values.length);
32
+ return createFormattedNode(exactNode, getStrInternalAllowedAnswerTypes(allowedAnsType));
33
+ };
34
+ const getAnswer = (identifiers) => {
35
+ return getAnswerNode(identifiers).toTex();
24
36
  };
25
37
  const getInstruction = (identifiers) => {
26
- const { target, values } = identifiers;
38
+ const { target, values, allowedAnsType } = identifiers;
27
39
  const length = values.length;
28
40
  return `Voici une liste de nombres :
29
41
 
@@ -35,7 +47,7 @@ $$
35
47
 
36
48
  Quelle est la fréquence d'apparition du nombre $${target}$ dans cette liste ?
37
49
 
38
- Donner la réponse sous forme de fraction, ou si possible de nombre décimal ou de pourcentage.`;
50
+ Donner ${getStrAllowedAnswerTypes(getStrInternalAllowedAnswerTypes(allowedAnsType))}.`;
39
51
  };
40
52
  const getHint = (identifiers) => {
41
53
  const { target } = identifiers;
@@ -59,25 +71,32 @@ $$
59
71
  const getKeys = () => {
60
72
  return ["percent"];
61
73
  };
62
- const isAnswerValid = (ans, { answer }) => {
74
+ const isAnswerValid = (ans, { answer, ...identifiers }) => {
63
75
  try {
76
+ let ansNode;
64
77
  if (ans.includes("%")) {
65
78
  const formated = ans.replace("\\%", "");
66
79
  const nb = formated.unfrenchify();
67
80
  if (isNaN(nb))
68
81
  return false;
69
- return (frac(nb, 100).simplify({ fractionsToDecimal: true }).toTex() === answer);
82
+ ansNode = frac(nb, 100);
70
83
  }
71
84
  else {
72
- const parsed = parseAlgebraic(ans);
73
- return parsed.simplify({ fractionsToDecimal: true }).toTex() === answer;
85
+ ansNode = parseAlgebraic(ans);
74
86
  }
87
+ if (!ansNode)
88
+ return false;
89
+ return getAllValidNodes(identifiers).some((answerNode) => {
90
+ return substract(ansNode, answerNode).simplify().evaluate() === 0;
91
+ });
75
92
  }
76
93
  catch (err) {
77
94
  return handleVEAError(err);
78
95
  }
79
96
  };
80
- const getCalculateFrequencyInListQuestion = () => {
97
+ const getCalculateFrequencyInListQuestion = (optsIn) => {
98
+ const opts = optsIn ?? optsDefault;
99
+ const allowedAnsType = opts.allowedAnsType;
81
100
  const target = randint(1, 10);
82
101
  const length = randint(6, 13);
83
102
  const values = [];
@@ -87,10 +106,11 @@ const getCalculateFrequencyInListQuestion = () => {
87
106
  const identifiers = {
88
107
  target,
89
108
  values,
109
+ allowedAnsType,
90
110
  };
91
111
  return getQuestionFromIdentifiers(identifiers);
92
112
  };
93
- const getQuestionFromIdentifiers = (identifiers) => {
113
+ const getQuestionFromIdentifiers = (identifiers, opts) => {
94
114
  return {
95
115
  answer: getAnswer(identifiers),
96
116
  instruction: getInstruction(identifiers),
@@ -99,14 +119,57 @@ const getQuestionFromIdentifiers = (identifiers) => {
99
119
  identifiers,
100
120
  hint: getHint(identifiers),
101
121
  correction: getCorrection(identifiers),
122
+ options: opts,
102
123
  };
103
124
  };
125
+ const getStrInternalAllowedAnswerTypes = (allowedAnsType) => {
126
+ return allowedAnsType.toSorted((a, b) => a.localeCompare(b)).join(" | ");
127
+ };
128
+ const getStrAllowedAnswerTypes = (strInternalAllowedAnswerTypes) => {
129
+ switch (strInternalAllowedAnswerTypes) {
130
+ case "arrondie à 2 décimales | exacte":
131
+ return "la valeur exacte ou la valeur arrondie à $2$ décimales";
132
+ case "arrondie à 2 décimales":
133
+ return "la valeur arrondie à $2$ décimales";
134
+ case "exacte":
135
+ return "la valeur exacte";
136
+ }
137
+ };
138
+ const createFormattedNode = (exactNode, strInternalAllowedAnswerTypes) => {
139
+ switch (strInternalAllowedAnswerTypes) {
140
+ case "arrondie à 2 décimales":
141
+ return round(exactNode.evaluate(), 2).toTree();
142
+ default:
143
+ return exactNode;
144
+ }
145
+ };
146
+ const getAllValidNodes = (identifiers) => {
147
+ return identifiers.allowedAnsType.map((ansType) => getAnswerNode((() => {
148
+ const identifiersCopy = Object.assign({}, identifiers);
149
+ identifiersCopy.allowedAnsType = [ansType];
150
+ return identifiersCopy;
151
+ })()));
152
+ };
153
+ const optsDefault = {
154
+ allowedAnsType: ["exacte", "arrondie à 2 décimales"],
155
+ };
156
+ const options = [
157
+ {
158
+ id: "allowedAnsType",
159
+ label: "Forme de réponse acceptée",
160
+ target: GeneratorOptionTarget.generation,
161
+ type: GeneratorOptionType.multiselect,
162
+ values: ["exacte", "arrondie à 2 décimales"],
163
+ defaultValue: optsDefault.allowedAnsType,
164
+ },
165
+ ];
104
166
  export const calculateFrequencyInList = {
105
167
  id: "calculateFrequencyInList",
106
168
  connector: "=",
107
169
  label: "Calculer la fréquence d'apparition d'un nombre dans une liste",
108
170
  isSingleStep: true,
109
171
  generator: (nb, opts) => getDistinctQuestions(() => getCalculateFrequencyInListQuestion(opts), nb),
172
+ options,
110
173
  qcmTimer: 60,
111
174
  freeTimer: 60,
112
175
  getPropositions,
@@ -114,4 +177,5 @@ export const calculateFrequencyInList = {
114
177
  subject: "Mathématiques",
115
178
  getQuestionFromIdentifiers,
116
179
  hasHintAndCorrection: true,
180
+ rebuildIdentifiers: rebuildIdentifiers,
117
181
  };