math-exercises 3.0.150 → 3.0.152

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 (217) hide show
  1. package/lib/exercises/exercise.d.ts +5 -0
  2. package/lib/exercises/exercise.d.ts.map +1 -1
  3. package/lib/exercises/math/calcul/arithmetics/primeNumbersAffirmations.js +1 -1
  4. package/lib/exercises/math/calcul/fractions/fractionToPercentToDecimal.d.ts +5 -1
  5. package/lib/exercises/math/calcul/fractions/fractionToPercentToDecimal.d.ts.map +1 -1
  6. package/lib/exercises/math/calcul/fractions/fractionToPercentToDecimal.js +92 -38
  7. package/lib/exercises/math/calcul/proportionality/findCoeffInProportionalTableNonIntegers.d.ts.map +1 -1
  8. package/lib/exercises/math/calcul/proportionality/findCoeffInProportionalTableNonIntegers.js +5 -1
  9. package/lib/exercises/math/calcul/proportionality/isTableProportional.d.ts.map +1 -1
  10. package/lib/exercises/math/calcul/proportionality/isTableProportional.js +7 -1
  11. package/lib/exercises/math/calcul/proportionality/isTableProportionalNonInteger.d.ts.map +1 -1
  12. package/lib/exercises/math/calcul/proportionality/isTableProportionalNonInteger.js +5 -1
  13. package/lib/exercises/math/calcul/proportionality/proportionalityTable.d.ts.map +1 -1
  14. package/lib/exercises/math/calcul/proportionality/proportionalityTable.js +5 -1
  15. package/lib/exercises/math/calcul/proportionality/proportionalityTableCoefficient.d.ts.map +1 -1
  16. package/lib/exercises/math/calcul/proportionality/proportionalityTableCoefficient.js +8 -2
  17. package/lib/exercises/math/calculLitteral/equation/equa1.d.ts +4 -1
  18. package/lib/exercises/math/calculLitteral/equation/equa1.d.ts.map +1 -1
  19. package/lib/exercises/math/calculLitteral/equation/equa1.js +27 -7
  20. package/lib/exercises/math/calculLitteral/equation/equa2.d.ts +1 -0
  21. package/lib/exercises/math/calculLitteral/equation/equa2.d.ts.map +1 -1
  22. package/lib/exercises/math/calculLitteral/equation/equa2.js +18 -1
  23. package/lib/exercises/math/calculLitteral/equation/equa3.d.ts +4 -1
  24. package/lib/exercises/math/calculLitteral/equation/equa3.d.ts.map +1 -1
  25. package/lib/exercises/math/calculLitteral/equation/equa3.js +26 -6
  26. package/lib/exercises/math/calculLitteral/equation/equa4.d.ts +4 -1
  27. package/lib/exercises/math/calculLitteral/equation/equa4.d.ts.map +1 -1
  28. package/lib/exercises/math/calculLitteral/equation/equa4.js +27 -7
  29. package/lib/exercises/math/calculLitteral/equation/firstDegree/equa1.d.ts +14 -0
  30. package/lib/exercises/math/calculLitteral/equation/firstDegree/equa1.d.ts.map +1 -0
  31. package/lib/exercises/math/calculLitteral/equation/firstDegree/equa1.js +129 -0
  32. package/lib/exercises/math/calculLitteral/equation/firstDegree/equa2.d.ts +18 -0
  33. package/lib/exercises/math/calculLitteral/equation/firstDegree/equa2.d.ts.map +1 -0
  34. package/lib/exercises/math/calculLitteral/equation/firstDegree/equa2.js +167 -0
  35. package/lib/exercises/math/calculLitteral/equation/firstDegree/equa3.d.ts +15 -0
  36. package/lib/exercises/math/calculLitteral/equation/firstDegree/equa3.d.ts.map +1 -0
  37. package/lib/exercises/math/calculLitteral/equation/firstDegree/equa3.js +129 -0
  38. package/lib/exercises/math/calculLitteral/equation/firstDegree/equa4.d.ts +16 -0
  39. package/lib/exercises/math/calculLitteral/equation/firstDegree/equa4.d.ts.map +1 -0
  40. package/lib/exercises/math/calculLitteral/equation/firstDegree/equa4.js +124 -0
  41. package/lib/exercises/math/calculLitteral/equation/firstDegree/firstDegreeEquationIntType1.d.ts +9 -0
  42. package/lib/exercises/math/calculLitteral/equation/firstDegree/firstDegreeEquationIntType1.d.ts.map +1 -0
  43. package/lib/exercises/math/calculLitteral/equation/firstDegree/firstDegreeEquationIntType1.js +107 -0
  44. package/lib/exercises/math/calculLitteral/equation/firstDegree/firstDegreeEquationIntType2.d.ts +10 -0
  45. package/lib/exercises/math/calculLitteral/equation/firstDegree/firstDegreeEquationIntType2.d.ts.map +1 -0
  46. package/lib/exercises/math/calculLitteral/equation/firstDegree/firstDegreeEquationIntType2.js +108 -0
  47. package/lib/exercises/math/calculLitteral/equation/firstDegree/firstDegreeEquationIntType3.d.ts +11 -0
  48. package/lib/exercises/math/calculLitteral/equation/firstDegree/firstDegreeEquationIntType3.d.ts.map +1 -0
  49. package/lib/exercises/math/calculLitteral/equation/firstDegree/firstDegreeEquationIntType3.js +104 -0
  50. package/lib/exercises/math/calculLitteral/equation/firstDegree/index.d.ts +8 -0
  51. package/lib/exercises/math/calculLitteral/equation/firstDegree/index.d.ts.map +1 -0
  52. package/lib/exercises/math/calculLitteral/equation/firstDegree/index.js +7 -0
  53. package/lib/exercises/math/calculLitteral/equation/index.d.ts +1 -7
  54. package/lib/exercises/math/calculLitteral/equation/index.d.ts.map +1 -1
  55. package/lib/exercises/math/calculLitteral/equation/index.js +1 -7
  56. package/lib/exercises/math/dataRepresentations/histogram/etendueHistogram.d.ts +8 -0
  57. package/lib/exercises/math/dataRepresentations/histogram/etendueHistogram.d.ts.map +1 -0
  58. package/lib/exercises/math/dataRepresentations/histogram/etendueHistogram.js +175 -0
  59. package/lib/exercises/math/dataRepresentations/histogram/histogramCommenting.d.ts +9 -0
  60. package/lib/exercises/math/dataRepresentations/histogram/histogramCommenting.d.ts.map +1 -0
  61. package/lib/exercises/math/dataRepresentations/histogram/histogramCommenting.js +250 -0
  62. package/lib/exercises/math/dataRepresentations/histogram/histogramFillDataTableFromHistogramData.d.ts +9 -0
  63. package/lib/exercises/math/dataRepresentations/histogram/histogramFillDataTableFromHistogramData.d.ts.map +1 -0
  64. package/lib/exercises/math/dataRepresentations/histogram/histogramFillDataTableFromHistogramData.js +173 -0
  65. package/lib/exercises/math/dataRepresentations/histogram/histogramIsSameData.d.ts +14 -0
  66. package/lib/exercises/math/dataRepresentations/histogram/histogramIsSameData.d.ts.map +1 -0
  67. package/lib/exercises/math/dataRepresentations/histogram/histogramIsSameData.js +239 -0
  68. package/lib/exercises/math/dataRepresentations/histogram/histogramReading.d.ts +9 -0
  69. package/lib/exercises/math/dataRepresentations/histogram/histogramReading.d.ts.map +1 -0
  70. package/lib/exercises/math/dataRepresentations/histogram/histogramReading.js +163 -0
  71. package/lib/exercises/math/dataRepresentations/histogram/index.d.ts +6 -0
  72. package/lib/exercises/math/dataRepresentations/histogram/index.d.ts.map +1 -0
  73. package/lib/exercises/math/dataRepresentations/histogram/index.js +5 -0
  74. package/lib/exercises/math/dataRepresentations/index.d.ts +1 -1
  75. package/lib/exercises/math/dataRepresentations/index.d.ts.map +1 -1
  76. package/lib/exercises/math/dataRepresentations/index.js +1 -1
  77. package/lib/exercises/math/dataRepresentations/tableReading.d.ts.map +1 -1
  78. package/lib/exercises/math/dataRepresentations/tableReading.js +7 -0
  79. package/lib/exercises/math/functions/affines/affineAdjustment.d.ts.map +1 -1
  80. package/lib/exercises/math/functions/affines/affineAdjustment.js +7 -1
  81. package/lib/exercises/math/functions/affines/affineAdjustmentComplete.d.ts.map +1 -1
  82. package/lib/exercises/math/functions/affines/affineAdjustmentComplete.js +7 -1
  83. package/lib/exercises/math/functions/affines/affineAdjustmentRsquared.d.ts.map +1 -1
  84. package/lib/exercises/math/functions/affines/affineAdjustmentRsquared.js +7 -1
  85. package/lib/exercises/math/functions/affines/leadingCoeffAndOriginOrdinate.d.ts +4 -1
  86. package/lib/exercises/math/functions/affines/leadingCoeffAndOriginOrdinate.d.ts.map +1 -1
  87. package/lib/exercises/math/functions/affines/leadingCoeffAndOriginOrdinate.js +19 -4
  88. package/lib/exercises/math/functions/affines/leadingCoefficient.d.ts +1 -0
  89. package/lib/exercises/math/functions/affines/leadingCoefficient.d.ts.map +1 -1
  90. package/lib/exercises/math/functions/affines/leadingCoefficient.js +13 -1
  91. package/lib/exercises/math/functions/affines/recognizeAffineGraph.d.ts +4 -1
  92. package/lib/exercises/math/functions/affines/recognizeAffineGraph.d.ts.map +1 -1
  93. package/lib/exercises/math/functions/affines/recognizeAffineGraph.js +19 -4
  94. package/lib/exercises/math/functions/basics/inverseImageFunctionTable.d.ts.map +1 -1
  95. package/lib/exercises/math/functions/basics/inverseImageFunctionTable.js +7 -1
  96. package/lib/exercises/math/functions/basics/placePointsFromValueTable.d.ts.map +1 -1
  97. package/lib/exercises/math/functions/basics/placePointsFromValueTable.js +7 -0
  98. package/lib/exercises/math/geometry/euclidian/pythagoreOrThales.d.ts +4 -1
  99. package/lib/exercises/math/geometry/euclidian/pythagoreOrThales.d.ts.map +1 -1
  100. package/lib/exercises/math/geometry/euclidian/pythagoreOrThales.js +18 -3
  101. package/lib/exercises/math/geometry/triangles/index.d.ts +1 -0
  102. package/lib/exercises/math/geometry/triangles/index.d.ts.map +1 -1
  103. package/lib/exercises/math/geometry/triangles/index.js +1 -0
  104. package/lib/exercises/math/geometry/triangles/similar/index.d.ts +4 -0
  105. package/lib/exercises/math/geometry/triangles/similar/index.d.ts.map +1 -0
  106. package/lib/exercises/math/geometry/triangles/similar/index.js +3 -0
  107. package/lib/exercises/math/geometry/triangles/similar/isSimilarTrianglesWithAngles.d.ts +10 -0
  108. package/lib/exercises/math/geometry/triangles/similar/isSimilarTrianglesWithAngles.d.ts.map +1 -0
  109. package/lib/exercises/math/geometry/triangles/similar/isSimilarTrianglesWithAngles.js +122 -0
  110. package/lib/exercises/math/geometry/triangles/similar/isSimilarTrianglesWrtSideLengths.d.ts +15 -0
  111. package/lib/exercises/math/geometry/triangles/similar/isSimilarTrianglesWrtSideLengths.d.ts.map +1 -0
  112. package/lib/exercises/math/geometry/triangles/similar/isSimilarTrianglesWrtSideLengths.js +351 -0
  113. package/lib/exercises/math/geometry/triangles/similar/placeSegmentsOfSimilarTriangle.d.ts +11 -0
  114. package/lib/exercises/math/geometry/triangles/similar/placeSegmentsOfSimilarTriangle.d.ts.map +1 -0
  115. package/lib/exercises/math/geometry/triangles/similar/placeSegmentsOfSimilarTriangle.js +311 -0
  116. package/lib/exercises/math/probaStat/basicProbas/calculateProbaFromProbaLaw.d.ts +10 -0
  117. package/lib/exercises/math/probaStat/basicProbas/calculateProbaFromProbaLaw.d.ts.map +1 -0
  118. package/lib/exercises/math/probaStat/basicProbas/calculateProbaFromProbaLaw.js +135 -0
  119. package/lib/exercises/math/probaStat/basicProbas/findEffectifFromProba.d.ts +9 -0
  120. package/lib/exercises/math/probaStat/basicProbas/findEffectifFromProba.d.ts.map +1 -0
  121. package/lib/exercises/math/probaStat/basicProbas/findEffectifFromProba.js +109 -0
  122. package/lib/exercises/math/probaStat/basicProbas/getMissingProbabilityValue.d.ts.map +1 -1
  123. package/lib/exercises/math/probaStat/basicProbas/getMissingProbabilityValue.js +7 -0
  124. package/lib/exercises/math/probaStat/basicProbas/getMissingProbabilityValueMiddleSchool.d.ts +9 -0
  125. package/lib/exercises/math/probaStat/basicProbas/getMissingProbabilityValueMiddleSchool.d.ts.map +1 -0
  126. package/lib/exercises/math/probaStat/basicProbas/getMissingProbabilityValueMiddleSchool.js +120 -0
  127. package/lib/exercises/math/probaStat/basicProbas/index.d.ts +4 -0
  128. package/lib/exercises/math/probaStat/basicProbas/index.d.ts.map +1 -1
  129. package/lib/exercises/math/probaStat/basicProbas/index.js +4 -0
  130. package/lib/exercises/math/probaStat/basicProbas/pickEquiprobableTo.d.ts +12 -0
  131. package/lib/exercises/math/probaStat/basicProbas/pickEquiprobableTo.d.ts.map +1 -0
  132. package/lib/exercises/math/probaStat/basicProbas/pickEquiprobableTo.js +374 -0
  133. package/lib/exercises/math/probaStat/probaFromTableNoContext.d.ts.map +1 -1
  134. package/lib/exercises/math/probaStat/probaFromTableNoContext.js +7 -0
  135. package/lib/exercises/math/probaStat/probaFromTableWithContext.d.ts.map +1 -1
  136. package/lib/exercises/math/probaStat/probaFromTableWithContext.js +7 -0
  137. package/lib/exercises/math/probaStat/stats1var/averageWithTable.d.ts.map +1 -1
  138. package/lib/exercises/math/probaStat/stats1var/averageWithTable.js +7 -1
  139. package/lib/exercises/math/probaStat/stats1var/calculateMeanFromFrequencies.d.ts.map +1 -1
  140. package/lib/exercises/math/probaStat/stats1var/calculateMeanFromFrequencies.js +7 -0
  141. package/lib/exercises/math/probaStat/stats1var/cumulativeSum.d.ts.map +1 -1
  142. package/lib/exercises/math/probaStat/stats1var/cumulativeSum.js +7 -0
  143. package/lib/exercises/math/probaStat/stats1var/etendueTable.d.ts.map +1 -1
  144. package/lib/exercises/math/probaStat/stats1var/etendueTable.js +7 -1
  145. package/lib/exercises/math/probaStat/stats1var/getQuartileProportionQuestion.d.ts.map +1 -1
  146. package/lib/exercises/math/probaStat/stats1var/getQuartileProportionQuestion.js +7 -0
  147. package/lib/exercises/math/probaStat/stats1var/interquartilesTable.d.ts.map +1 -1
  148. package/lib/exercises/math/probaStat/stats1var/interquartilesTable.js +5 -1
  149. package/lib/exercises/math/probaStat/stats1var/marginalAndConditionalFrequency.d.ts.map +1 -1
  150. package/lib/exercises/math/probaStat/stats1var/marginalAndConditionalFrequency.js +7 -0
  151. package/lib/exercises/math/probaStat/stats1var/medianWithList.d.ts +2 -0
  152. package/lib/exercises/math/probaStat/stats1var/medianWithList.d.ts.map +1 -1
  153. package/lib/exercises/math/probaStat/stats1var/medianWithList.js +67 -14
  154. package/lib/exercises/math/probaStat/stats1var/medianWithTable.d.ts.map +1 -1
  155. package/lib/exercises/math/probaStat/stats1var/medianWithTable.js +7 -1
  156. package/lib/exercises/math/probaStat/stats1var/quartiles.d.ts.map +1 -1
  157. package/lib/exercises/math/probaStat/stats1var/quartiles.js +7 -1
  158. package/lib/exercises/math/probaStat/stats1var/standardDeviationTable.d.ts.map +1 -1
  159. package/lib/exercises/math/probaStat/stats1var/standardDeviationTable.js +5 -1
  160. package/lib/exercises/math/probaStat/stats1var/varianceTable.d.ts.map +1 -1
  161. package/lib/exercises/math/probaStat/stats1var/varianceTable.js +5 -1
  162. package/lib/exercises/math/probaStat/stats2var/averagePoint.d.ts.map +1 -1
  163. package/lib/exercises/math/probaStat/stats2var/averagePoint.js +7 -1
  164. package/lib/exercises/math/probaStat/twoStepExperiments/headsOrTailsTwiceOutcomes.d.ts +7 -0
  165. package/lib/exercises/math/probaStat/twoStepExperiments/headsOrTailsTwiceOutcomes.d.ts.map +1 -0
  166. package/lib/exercises/math/probaStat/twoStepExperiments/headsOrTailsTwiceOutcomes.js +171 -0
  167. package/lib/exercises/math/probaStat/twoStepExperiments/headsOrTailsTwiceProbas.d.ts +7 -0
  168. package/lib/exercises/math/probaStat/twoStepExperiments/headsOrTailsTwiceProbas.d.ts.map +1 -0
  169. package/lib/exercises/math/probaStat/twoStepExperiments/headsOrTailsTwiceProbas.js +155 -0
  170. package/lib/exercises/math/probaStat/twoStepExperiments/index.d.ts +3 -0
  171. package/lib/exercises/math/probaStat/twoStepExperiments/index.d.ts.map +1 -1
  172. package/lib/exercises/math/probaStat/twoStepExperiments/index.js +3 -0
  173. package/lib/exercises/math/probaStat/twoStepExperiments/numberPoolTwiceProbas.d.ts +7 -0
  174. package/lib/exercises/math/probaStat/twoStepExperiments/numberPoolTwiceProbas.d.ts.map +1 -0
  175. package/lib/exercises/math/probaStat/twoStepExperiments/numberPoolTwiceProbas.js +189 -0
  176. package/lib/exercises/math/spaceGeometry/index.d.ts +1 -0
  177. package/lib/exercises/math/spaceGeometry/index.d.ts.map +1 -1
  178. package/lib/exercises/math/spaceGeometry/index.js +1 -0
  179. package/lib/exercises/math/spaceGeometry/sections/areaOfConeSection.d.ts +14 -0
  180. package/lib/exercises/math/spaceGeometry/sections/areaOfConeSection.d.ts.map +1 -0
  181. package/lib/exercises/math/spaceGeometry/sections/areaOfConeSection.js +439 -0
  182. package/lib/exercises/math/spaceGeometry/sections/areaOfCylinderSection.d.ts +14 -0
  183. package/lib/exercises/math/spaceGeometry/sections/areaOfCylinderSection.d.ts.map +1 -0
  184. package/lib/exercises/math/spaceGeometry/sections/areaOfCylinderSection.js +548 -0
  185. package/lib/exercises/math/spaceGeometry/sections/areaOfRectangularPrismSection.d.ts +11 -0
  186. package/lib/exercises/math/spaceGeometry/sections/areaOfRectangularPrismSection.d.ts.map +1 -0
  187. package/lib/exercises/math/spaceGeometry/sections/areaOfRectangularPrismSection.js +360 -0
  188. package/lib/exercises/math/spaceGeometry/sections/areaOfSphereSection.d.ts +9 -0
  189. package/lib/exercises/math/spaceGeometry/sections/areaOfSphereSection.d.ts.map +1 -0
  190. package/lib/exercises/math/spaceGeometry/sections/areaOfSphereSection.js +272 -0
  191. package/lib/exercises/math/spaceGeometry/sections/index.d.ts +9 -0
  192. package/lib/exercises/math/spaceGeometry/sections/index.d.ts.map +1 -0
  193. package/lib/exercises/math/spaceGeometry/sections/index.js +8 -0
  194. package/lib/exercises/math/spaceGeometry/sections/recognizeSectionsOfCone.d.ts +11 -0
  195. package/lib/exercises/math/spaceGeometry/sections/recognizeSectionsOfCone.d.ts.map +1 -0
  196. package/lib/exercises/math/spaceGeometry/sections/recognizeSectionsOfCone.js +266 -0
  197. package/lib/exercises/math/spaceGeometry/sections/recognizeSectionsOfCylinder.d.ts +11 -0
  198. package/lib/exercises/math/spaceGeometry/sections/recognizeSectionsOfCylinder.d.ts.map +1 -0
  199. package/lib/exercises/math/spaceGeometry/sections/recognizeSectionsOfCylinder.js +236 -0
  200. package/lib/exercises/math/spaceGeometry/sections/recognizeSectionsOfRectangularPrism.d.ts +7 -0
  201. package/lib/exercises/math/spaceGeometry/sections/recognizeSectionsOfRectangularPrism.d.ts.map +1 -0
  202. package/lib/exercises/math/spaceGeometry/sections/recognizeSectionsOfRectangularPrism.js +92 -0
  203. package/lib/exercises/math/spaceGeometry/sections/recognizeSectionsOfSphereOrBall.d.ts +9 -0
  204. package/lib/exercises/math/spaceGeometry/sections/recognizeSectionsOfSphereOrBall.d.ts.map +1 -0
  205. package/lib/exercises/math/spaceGeometry/sections/recognizeSectionsOfSphereOrBall.js +236 -0
  206. package/lib/exercises/pc/mathExosInPC.d.ts +4 -4
  207. package/lib/exercises/pc/mathExosInPC.d.ts.map +1 -1
  208. package/lib/exercises/pc/mathExosInPC.js +4 -4
  209. package/lib/index.d.ts +173 -45
  210. package/lib/index.d.ts.map +1 -1
  211. package/lib/math/geometry/spacePoint.d.ts +10 -0
  212. package/lib/math/geometry/spacePoint.d.ts.map +1 -1
  213. package/lib/math/geometry/spacePoint.js +13 -0
  214. package/lib/tree/nodes/operators/substractNode.d.ts +1 -0
  215. package/lib/tree/nodes/operators/substractNode.d.ts.map +1 -1
  216. package/lib/tree/nodes/operators/substractNode.js +6 -0
  217. package/package.json +1 -1
@@ -0,0 +1,351 @@
1
+ import { addValidProp, tryToAddWrongProp, GeneratorOptionTarget, GeneratorOptionType, } from "../../../../../exercises/exercise.js";
2
+ import { getDistinctQuestions } from "../../../../../exercises/utils/getDistinctQuestions.js";
3
+ import { primes } from "../../../../../math/numbers/integer/primes.js";
4
+ import { gcd } from "../../../../../math/utils/arithmetic/gcd.js";
5
+ import { randint } from "../../../../../math/utils/random/randint.js";
6
+ import { round } from "../../../../../math/utils/round.js";
7
+ import { NodeConstructor, } from "../../../../../tree/nodes/nodeConstructor.js";
8
+ import { add } from "../../../../../tree/nodes/operators/addNode.js";
9
+ import { frac } from "../../../../../tree/nodes/operators/fractionNode.js";
10
+ import { multiply } from "../../../../../tree/nodes/operators/multiplyNode.js";
11
+ import { substract } from "../../../../../tree/nodes/operators/substractNode.js";
12
+ import { coinFlip } from "../../../../../utils/alea/coinFlip.js";
13
+ import { random, randomMany } from "../../../../../utils/alea/random.js";
14
+ import { shuffle } from "../../../../../utils/alea/shuffle.js";
15
+ import { alignTex } from "../../../../../utils/latex/alignTex.js";
16
+ import { joinanded } from "../../../../../utils/strings/joinanded.js";
17
+ const getNAllDigits = (n) => {
18
+ const strN = n.frenchify();
19
+ if (strN.includes(",")) {
20
+ const [leftOfSep, rightOfSep] = strN.split(",");
21
+ const roundTo = 1;
22
+ const nAllDigits = parseInt(leftOfSep + rightOfSep.slice(0, roundTo));
23
+ return nAllDigits;
24
+ }
25
+ else {
26
+ return n;
27
+ }
28
+ };
29
+ const extendedGcd = (n1, n2) => {
30
+ try {
31
+ const [n1AllDigits, n2AllDigits] = [n1, n2].map(getNAllDigits);
32
+ const commonDivisor = gcd(n1AllDigits, n2AllDigits);
33
+ return commonDivisor;
34
+ }
35
+ catch (_) {
36
+ return 1;
37
+ }
38
+ };
39
+ const getHydratedObjs = (identifiers) => {
40
+ const { nodeIdsLengths1, nodeIdsLengths2, namePoints1, namePoints2 } = identifiers;
41
+ const [nodeLengths1, nodeLengths2] = [nodeIdsLengths1, nodeIdsLengths2].map((arrNodeIds) => arrNodeIds.map((nodeIds) => NodeConstructor.fromIdentifiers(nodeIds).simplify({
42
+ fractionsToDecimal: true,
43
+ })));
44
+ const [nameTriangle1, nameTriangle2] = [namePoints1, namePoints2].map((pointNames) => pointNames.join(""));
45
+ const [nameSegments1, nameSegments2] = [namePoints1, namePoints2].map((pointNames) => [
46
+ [0, 1],
47
+ [1, 2],
48
+ [2, 0],
49
+ ].map(([i1, i2]) => `${pointNames[i1]}${pointNames[i2]}`));
50
+ return {
51
+ nodeLengths1,
52
+ nodeLengths2,
53
+ nameTriangle1,
54
+ nameTriangle2,
55
+ nameSegments1,
56
+ nameSegments2,
57
+ };
58
+ };
59
+ const isSimilar = (identifiers) => {
60
+ const { nodeLengths1, nodeLengths2 } = getHydratedObjs(identifiers);
61
+ const [nodeLengths1SortedAsc, nodeLengths2SortedAsc] = [
62
+ nodeLengths1,
63
+ nodeLengths2,
64
+ ].map((nodeLengths) => nodeLengths.toSorted((node1, node2) => node1.evaluate() - node2.evaluate()));
65
+ const nodeCoeffs = nodeLengths2SortedAsc.map((nodeLength2, i) => frac(nodeLength2, nodeLengths1SortedAsc[i]));
66
+ const nodeCoeff0 = nodeCoeffs[0].simplify();
67
+ return nodeCoeffs.slice(1).every((nodeCoeff) => {
68
+ return (substract(nodeCoeff.simplify(), nodeCoeff0).simplify().evaluate() === 0);
69
+ });
70
+ };
71
+ const getPropositions = (_, { answer, ...identifiers }) => {
72
+ const propositions = [];
73
+ const answerFromIdentifiers = getAnswer(identifiers);
74
+ ["Oui", "Non"].forEach((strProp) => {
75
+ if (strProp === answerFromIdentifiers) {
76
+ addValidProp(propositions, strProp, "raw");
77
+ }
78
+ else {
79
+ tryToAddWrongProp(propositions, strProp, "raw");
80
+ }
81
+ });
82
+ return propositions;
83
+ };
84
+ const getAnswer = (identifiers) => {
85
+ return isSimilar(identifiers) ? "Oui" : "Non";
86
+ };
87
+ const getInstruction = (identifiers) => {
88
+ const { nodeLengths1, nodeLengths2, nameTriangle1, nameTriangle2, nameSegments1, nameSegments2, } = getHydratedObjs(identifiers);
89
+ return `Soit $${nameTriangle1}$ un triangle tel que ${joinanded(nameSegments1.map((nameSegment, i) => `$${nameSegment} = ${nodeLengths1[i].toTex()} \\ \\textrm{cm}$`), ", ", " et ")}.
90
+ Soit $${nameTriangle2}$ un triangle tel que ${joinanded(nameSegments2.map((nameSegment, i) => `$${nameSegment} = ${nodeLengths2[i].toTex()} \\ \\textrm{cm}$`), ", ", " et ")}.
91
+
92
+ Les triangles $${nameTriangle1}$ et $${nameTriangle2}$ sont-ils semblables ?`;
93
+ };
94
+ const getHint = (identifiers) => {
95
+ const { namePoints1, namePoints2 } = identifiers;
96
+ const [nameTriangle1, nameTriangle2] = [namePoints1, namePoints2].map((pointNames) => pointNames.join(""));
97
+ return `Regarde si tu peux trouver un coefficient de proportionnalité entre les longueurs de $${nameTriangle1}$ et celles de $${nameTriangle2}$ (même prises dans un autre ordre).`;
98
+ };
99
+ const getCorrection = (identifiers) => {
100
+ const { nodeLengths1, nodeLengths2, nameTriangle1, nameTriangle2 } = getHydratedObjs(identifiers);
101
+ const [nodeLengths1SortedAsc, nodeLengths2SortedAsc] = [
102
+ nodeLengths1,
103
+ nodeLengths2,
104
+ ].map((nodeLengths) => nodeLengths.toSorted((node1, node2) => node1.evaluate() - node2.evaluate()));
105
+ const nodeCoeffs = nodeLengths2SortedAsc.map((nodeLength2, i) => frac(nodeLength2, nodeLengths1SortedAsc[i]));
106
+ const isSim = isSimilar(identifiers);
107
+ return `Pour ne pas avoir à tester tous les cas possibles, pour chaque triangle, on range les longueurs par ordre croissant.
108
+
109
+ Pour $${nameTriangle1}$ :
110
+
111
+ $$
112
+ ${nodeLengths1SortedAsc.map((node) => node.toTex()).join(" < ")}
113
+ $$
114
+
115
+ Pour $${nameTriangle2}$ :
116
+
117
+ $$
118
+ ${nodeLengths2SortedAsc.map((node) => node.toTex()).join(" < ")}
119
+ $$
120
+
121
+ On regarde ensuite si les rapports $\\frac{\\text{longueur dans ${nameTriangle2}}}{\\text{longueur dans ${nameTriangle1}}}$ sont tous égaux.
122
+
123
+ On a :
124
+
125
+ ${alignTex([0, 1, 2].map((i) => [
126
+ `${nodeCoeffs[i].toTex()}`,
127
+ "=",
128
+ `${nodeCoeffs[i].simplify({ fractionsToDecimal: true }).toTex()}`,
129
+ ]))}
130
+
131
+ Les triangles $${nameTriangle1}$ et $${nameTriangle2}$ ${isSim ? "sont donc semblables" : "ne sont donc pas semblables"}.`;
132
+ };
133
+ const getIsSimilarTrianglesWrtSideLengthsQuestion = (optsIn) => {
134
+ const opts = optsIn ?? optsDefault;
135
+ function createRandomNodeCoeff(numberTypeForCoeff) {
136
+ switch (numberTypeForCoeff) {
137
+ // case "Fraction":
138
+ // {
139
+ // return RationalConstructor.randomIrreductible().toTree();
140
+ // }
141
+ // break;
142
+ case "Décimal":
143
+ {
144
+ return round(randint(1, 20) + 0.1 * randint(1, 10), 1)
145
+ .toTree()
146
+ .simplify({ fractionsToDecimal: true });
147
+ }
148
+ break;
149
+ default:
150
+ case "Entier":
151
+ {
152
+ return randint(2, 10).toTree();
153
+ }
154
+ break;
155
+ }
156
+ }
157
+ function createRandomNodeLength(numberTypeForLength) {
158
+ switch (numberTypeForLength) {
159
+ case "Décimal":
160
+ {
161
+ return round(randint(2, 15) + 0.1 * randint(1, 10), 1)
162
+ .toTree()
163
+ .simplify({ fractionsToDecimal: true });
164
+ }
165
+ break;
166
+ default:
167
+ case "Entier":
168
+ {
169
+ return randint(2, 16).toTree();
170
+ }
171
+ break;
172
+ }
173
+ }
174
+ function isTriangleWrtSideLenghts(nodeLengths) {
175
+ return nodeLengths.every((nodeLength, i) => {
176
+ const nodeSumOfOther = nodeLengths
177
+ .filter((_, j) => j !== i)
178
+ .reduce((acc, x) => add(acc, x));
179
+ return nodeLength.evaluate() <= nodeSumOfOther.evaluate();
180
+ });
181
+ }
182
+ function createRandomTriangleNodes(numberTypesForLengths) {
183
+ let nodeLengths;
184
+ let isValidTriangle = false;
185
+ let counter = -1;
186
+ while (!isValidTriangle && counter < 100) {
187
+ counter++;
188
+ nodeLengths = [0, 1, 2].map(() => {
189
+ const numberTypeForLength = random(numberTypesForLengths);
190
+ return createRandomNodeLength(numberTypeForLength);
191
+ });
192
+ isValidTriangle = isTriangleWrtSideLenghts(nodeLengths);
193
+ }
194
+ if (!isValidTriangle) {
195
+ if (numberTypesForLengths.includes("Entier") &&
196
+ !numberTypesForLengths.includes("Décimal")) {
197
+ return [3, 4, 5].map((n) => n.toTree());
198
+ }
199
+ else if (!numberTypesForLengths.includes("Entier") &&
200
+ numberTypesForLengths.includes("Décimal")) {
201
+ return [3.3, 4.4, 5.5].map((n) => n.toTree());
202
+ }
203
+ else {
204
+ return [3.3, 4, 5.5].map((n) => n.toTree());
205
+ }
206
+ }
207
+ return nodeLengths;
208
+ }
209
+ function createRandomHighGcdTriangleNodes(numberTypesForLengths) {
210
+ let nodeLengths;
211
+ let isValidTriangle = false;
212
+ let counter = -1;
213
+ while (!isValidTriangle && counter < 100) {
214
+ counter++;
215
+ const commonDivisor = random(primes.filter((n) => 7 <= n && n <= 23));
216
+ const numberTypeForLength = random(numberTypesForLengths);
217
+ if (numberTypeForLength === "Entier") {
218
+ nodeLengths = randomMany([2, 3, 4, 5, 6, 7, 8], 3)
219
+ .map((n) => n * commonDivisor)
220
+ .map((n) => n.toTree())
221
+ .map((node) => round(node.evaluate(), 1).toTree());
222
+ }
223
+ else {
224
+ nodeLengths = randomMany([2, 3, 4, 5, 6, 7, 8], 3)
225
+ .map((n) => n * commonDivisor)
226
+ .map((n) => (n * 0.1).toTree())
227
+ .map((node) => round(node.evaluate(), 1).toTree());
228
+ }
229
+ isValidTriangle = isTriangleWrtSideLenghts(nodeLengths);
230
+ }
231
+ if (!isValidTriangle) {
232
+ if (numberTypesForLengths.includes("Entier") &&
233
+ !numberTypesForLengths.includes("Décimal")) {
234
+ return [3, 4, 5].map((n) => n.toTree());
235
+ }
236
+ else if (!numberTypesForLengths.includes("Entier") &&
237
+ numberTypesForLengths.includes("Décimal")) {
238
+ return [3.3, 4.4, 5.5].map((n) => n.toTree());
239
+ }
240
+ else {
241
+ return [3.3, 4, 5.5].map((n) => n.toTree());
242
+ }
243
+ }
244
+ return nodeLengths;
245
+ }
246
+ let isSimilar = coinFlip();
247
+ const numberTypeForCoeffCandidate = random(opts.numberTypesForCoeffs);
248
+ const nodeLengths1 = (() => {
249
+ if (numberTypeForCoeffCandidate === "Fraction") {
250
+ return createRandomHighGcdTriangleNodes(opts.numberTypesForLengths);
251
+ }
252
+ else {
253
+ return createRandomTriangleNodes(opts.numberTypesForLengths);
254
+ }
255
+ })();
256
+ const nodeLengths1SortedAsc = nodeLengths1.toSorted((node1, node2) => node1.evaluate() - node2.evaluate());
257
+ const createNodeCoeff = () => {
258
+ const numberTypeForCoeff = numberTypeForCoeffCandidate === "Fraction"
259
+ ? numberTypeForCoeffCandidate
260
+ : random(opts.numberTypesForCoeffs.filter((numberTypeForCoeff) => numberTypeForCoeff !== "Fraction"));
261
+ if (numberTypeForCoeff === "Fraction") {
262
+ const den = nodeLengths1
263
+ .reduce((acc, x) => extendedGcd(acc.evaluate(), x.evaluate()).toTree())
264
+ .evaluate();
265
+ const num = random(primes.filter((n) => n < 5 * den));
266
+ return frac(num, den);
267
+ }
268
+ else {
269
+ const nodeCoeff = createRandomNodeCoeff(numberTypeForCoeff);
270
+ return nodeCoeff;
271
+ }
272
+ };
273
+ const nodeCoeffs = isSimilar
274
+ ? (() => {
275
+ const nodeCoeff = createNodeCoeff();
276
+ return nodeLengths1.map(() => nodeCoeff);
277
+ })()
278
+ : nodeLengths1.map(() => createNodeCoeff());
279
+ const nodeCoeffsSortedAsc = nodeCoeffs.toSorted((node1, node2) => node1.evaluate() - node2.evaluate());
280
+ isSimilar = (() => {
281
+ const nodeCoeff0 = nodeCoeffsSortedAsc[0].simplify();
282
+ return nodeCoeffsSortedAsc.slice(1).every((nodeCoeff) => {
283
+ return (substract(nodeCoeff.simplify(), nodeCoeff0).simplify().evaluate() === 0);
284
+ });
285
+ })();
286
+ const nodeLengths2SortedAsc = nodeLengths1SortedAsc.map((nodeLength, i) => multiply(nodeCoeffsSortedAsc[i], nodeLength).simplify());
287
+ const nodeLengths1Shuffled = shuffle(nodeLengths1SortedAsc);
288
+ const nodeLengths2Shuffled = shuffle(nodeLengths2SortedAsc);
289
+ const [A, B, C, D, E, F] = randomMany("ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""), 6);
290
+ const namePoints1 = [A, B, C];
291
+ const namePoints2 = [D, E, F];
292
+ const identifiers = {
293
+ nodeIdsLengths1: nodeLengths1Shuffled.map((node) => node.toIdentifiers()),
294
+ nodeIdsLengths2: nodeLengths2Shuffled.map((node) => node.toIdentifiers()),
295
+ namePoints1,
296
+ namePoints2,
297
+ };
298
+ return getQuestionFromIdentifiers(identifiers);
299
+ };
300
+ const getQuestionFromIdentifiers = (identifiers, opts) => {
301
+ return {
302
+ answer: getAnswer(identifiers),
303
+ instruction: getInstruction(identifiers),
304
+ keys: [],
305
+ answerFormat: "raw",
306
+ identifiers,
307
+ hint: getHint(identifiers),
308
+ correction: getCorrection(identifiers),
309
+ options: opts,
310
+ };
311
+ };
312
+ const optsDefault = {
313
+ numberTypesForLengths: ["Décimal"],
314
+ numberTypesForCoeffs: ["Entier"],
315
+ };
316
+ const options = [
317
+ {
318
+ id: "numberTypesForLengths",
319
+ label: "Types de nombres pour les longueurs",
320
+ defaultValue: optsDefault.numberTypesForLengths,
321
+ values: ["Entier", "Décimal"],
322
+ target: GeneratorOptionTarget.generation,
323
+ type: GeneratorOptionType.multiselect,
324
+ },
325
+ {
326
+ id: "numberTypesForCoeffs",
327
+ label: "Types de nombres pour les rapports",
328
+ defaultValue: optsDefault.numberTypesForCoeffs,
329
+ values: ["Entier", "Décimal", "Fraction"],
330
+ target: GeneratorOptionTarget.generation,
331
+ type: GeneratorOptionType.multiselect,
332
+ },
333
+ ];
334
+ export const isSimilarTrianglesWrtSideLengths = {
335
+ id: "isSimilarTrianglesWrtSideLengths",
336
+ label: "Justifier que deux triangles sont semblables par le rapport de leurs côtés",
337
+ isSingleStep: true,
338
+ generator: (nb, opts) => getDistinctQuestions(() => getIsSimilarTrianglesWrtSideLengthsQuestion(opts), nb),
339
+ options,
340
+ qcmTimer: 60,
341
+ freeTimer: 60,
342
+ getPropositions,
343
+ subject: "Mathématiques",
344
+ getInstruction,
345
+ getHint,
346
+ getCorrection,
347
+ getAnswer,
348
+ getQuestionFromIdentifiers,
349
+ hasHintAndCorrection: true,
350
+ answerType: "QCU",
351
+ };
@@ -0,0 +1,11 @@
1
+ import { Exercise } from "../../../../../exercises/exercise.js";
2
+ import { TriangleIdentifiers } from "../../../../../math/geometry/triangles/triangle.js";
3
+ import { NodeIdentifiers } from "../../../../../tree/nodes/nodeConstructor.js";
4
+ type Identifiers = {
5
+ triangleIds1: TriangleIdentifiers;
6
+ triangleIds2: TriangleIdentifiers;
7
+ factor: NodeIdentifiers;
8
+ };
9
+ export declare const placeSegmentsOfSimilarTriangle: Exercise<Identifiers>;
10
+ export {};
11
+ //# sourceMappingURL=placeSegmentsOfSimilarTriangle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placeSegmentsOfSimilarTriangle.d.ts","sourceRoot":"","sources":["../../../../../../src/exercises/math/geometry/triangles/similar/placeSegmentsOfSimilarTriangle.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAWT,MAAM,6BAA6B,CAAC;AAQrC,OAAO,EAGL,mBAAmB,EACpB,MAAM,2CAA2C,CAAC;AAQnD,OAAO,EAEL,eAAe,EAChB,MAAM,qCAAqC,CAAC;AAwC7C,KAAK,WAAW,GAAG;IACjB,YAAY,EAAE,mBAAmB,CAAC;IAClC,YAAY,EAAE,mBAAmB,CAAC;IAClC,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAkXF,eAAO,MAAM,8BAA8B,EAAE,QAAQ,CAAC,WAAW,CAgBhE,CAAC"}
@@ -0,0 +1,311 @@
1
+ import { toolBarConstructor } from "../../../../../exercises/utils/geogebra/toolBarConstructor.js";
2
+ import { getDistinctQuestions } from "../../../../../exercises/utils/getDistinctQuestions.js";
3
+ import { greenMain, orange } from "../../../../../geogebra/colors.js";
4
+ import { GeogebraConstructor } from "../../../../../geogebra/geogebraConstructor.js";
5
+ import { Point } from "../../../../../math/geometry/point.js";
6
+ import { Segment } from "../../../../../math/geometry/segment.js";
7
+ import { Triangle, TriangleConstructor, } from "../../../../../math/geometry/triangles/triangle.js";
8
+ import { Vector, VectorConstructor } from "../../../../../math/geometry/vector.js";
9
+ import { dividersOf } from "../../../../../math/utils/arithmetic/dividersOf.js";
10
+ import { randfloat } from "../../../../../math/utils/random/randfloat.js";
11
+ import { randint } from "../../../../../math/utils/random/randint.js";
12
+ import { round } from "../../../../../math/utils/round.js";
13
+ import { opposite } from "../../../../../tree/nodes/functions/oppositeNode.js";
14
+ import { NodeConstructor, } from "../../../../../tree/nodes/nodeConstructor.js";
15
+ import { frac } from "../../../../../tree/nodes/operators/fractionNode.js";
16
+ import { random, randomMany } from "../../../../../utils/alea/random.js";
17
+ import { intersect } from "../../../../../utils/arrays/arrayIntersection.js";
18
+ function getCoordsForPoints(points) {
19
+ const xMin = Math.min(...points.map((p) => p.x.evaluate()));
20
+ const xMax = Math.max(...points.map((p) => p.x.evaluate()));
21
+ const yMin = Math.min(...points.map((p) => p.y.evaluate()));
22
+ const yMax = Math.max(...points.map((p) => p.y.evaluate()));
23
+ return { xMin, xMax, yMin, yMax };
24
+ }
25
+ const getDivisorsOfVector = (vec) => {
26
+ const arrDivisors = [vec.x, vec.y].map((z) => {
27
+ const n = Math.abs(z.evaluate());
28
+ if (n !== 0) {
29
+ return dividersOf(n);
30
+ }
31
+ else {
32
+ return [...Array(100).keys()].map((i) => i + 1); //everything divides 0
33
+ }
34
+ });
35
+ const divisorsOfVec = intersect(arrDivisors);
36
+ return divisorsOfVec;
37
+ };
38
+ const getRandomFactorNodeForVectors = (vecs) => {
39
+ const divisorsOfVecs = intersect(vecs.map((vec) => getDivisorsOfVector(vec)));
40
+ if (divisorsOfVecs.length !== 1) {
41
+ const den = random(divisorsOfVecs.filter((n) => n !== 1));
42
+ const num = randint(1, 3 * den, [den]);
43
+ const factorNode = frac(num, den);
44
+ return factorNode;
45
+ }
46
+ else {
47
+ return (1).toTree();
48
+ }
49
+ };
50
+ const getInstruction = (identifiers) => {
51
+ const { triangleIds1, triangleIds2 } = identifiers;
52
+ const [nameTriangle1, nameTriangle2] = [triangleIds1, triangleIds2].map((triangleIds) => `${triangleIds.points[0].name}${triangleIds.points[1].name}${triangleIds.points[2].name}`);
53
+ const [angles1, angles2] = [triangleIds1, triangleIds2].map((triangle) => [
54
+ `\\widehat{${triangle.points[0].name}}`,
55
+ `\\widehat{${triangle.points[1].name}}`,
56
+ ]);
57
+ return `Construire les deux segments manquants du triangle $${nameTriangle2}$ sachant que :
58
+
59
+ - $${nameTriangle1}$ et $${nameTriangle2}$ sont semblables et que
60
+
61
+ - $${angles1[0]} = ${angles2[1]}$ et $${angles1[1]} = ${angles2[0]}$`;
62
+ };
63
+ const getHint = (identifiers) => {
64
+ const { triangleIds1, triangleIds2 } = identifiers;
65
+ const [nameBaseSegment1, nameBaseSegment2] = [triangleIds1, triangleIds2].map((triangleIds) => `[${triangleIds.points[0].name}${triangleIds.points[1].name}]`);
66
+ return `Tu peux trouver le rapport d'agrandissement ou de réduction grâce aux segments $${nameBaseSegment1}$ et $${nameBaseSegment2}$.`;
67
+ };
68
+ const getCorrection = (identifiers) => {
69
+ const { triangleIds1, triangleIds2, factor } = identifiers;
70
+ const [nameBaseLength1, nameBaseLength2] = [triangleIds1, triangleIds2].map((triangleIds) => `${triangleIds.points[0].name}${triangleIds.points[1].name}`);
71
+ const [triangle1, triangle2] = [triangleIds1, triangleIds2].map((triangleIds) => TriangleConstructor.fromIdentifiers(triangleIds));
72
+ const vec1 = triangle1.sides[1].toVector();
73
+ const vec2 = triangle2.sides[0].toVector();
74
+ const [isLeft1, isLeft2] = [vec1, vec2].map((vec) => vec.x.evaluate() < 0);
75
+ const [absX1, absX2] = [vec1, vec2].map((vec) => Math.abs(vec.x.evaluate()));
76
+ const factorNode = NodeConstructor.fromIdentifiers(factor);
77
+ const [angles1, angles2] = [triangleIds1, triangleIds2].map((triangle) => [
78
+ `\\widehat{${triangle.points[0].name}}`,
79
+ `\\widehat{${triangle.points[1].name}}`,
80
+ ]);
81
+ return `Le rapport d'agrandissement ou de réduction vaut :
82
+
83
+ $$
84
+ \\frac{${nameBaseLength2}}{${nameBaseLength1}} = ${factorNode
85
+ .simplify()
86
+ .toTex()}
87
+ $$
88
+
89
+ Pour aller de $${triangle1.sides[1].pointA.name}$ à $${triangle1.sides[1].pointB.name}$,
90
+ on va $${absX1.frenchify()}$ cases vers la ${isLeft1 ? "gauche" : "droite"} et $${vec1.y.toTex()}$ cases vers le haut.
91
+ Il faut respecter les mesures d'angles :
92
+ On a $${angles1[0]} = ${angles2[1]}$.
93
+ Ainsi,
94
+ pour aller de $${triangle2.sides[0].pointA.name}$ à $${triangle2.sides[0].pointB.name}$,
95
+ on va $${absX2.frenchify()}$ cases vers la ${isLeft2 ? "gauche" : "droite"} et $${vec2.y.toTex()}$ cases vers le haut.
96
+ `;
97
+ };
98
+ const getCorrectionGGBOptions = (identifiers) => {
99
+ const { triangleIds1, triangleIds2 } = identifiers;
100
+ const [triangle1, triangle2] = [triangleIds1, triangleIds2].map((triangleIds) => TriangleConstructor.fromIdentifiers(triangleIds));
101
+ const ggb = new GeogebraConstructor({
102
+ hideAxes: true,
103
+ isGridSimple: true,
104
+ customToolBar: toolBarConstructor({ point: true, segment: true }),
105
+ commands: [
106
+ //triangles
107
+ ...triangle1.commands,
108
+ ...triangle2.commands,
109
+ //base segment
110
+ ...triangle2.sides[2].toGGBCommands(true),
111
+ `SetColor(${triangle2.sides[2].ggbName}, "${orange}")`,
112
+ ...getGGBAnswer(identifiers),
113
+ ],
114
+ fontSize: 16,
115
+ });
116
+ return ggb.getOptions({
117
+ coords: ggb.getCoordsForPoints([...triangle1.points, ...triangle2.points]),
118
+ });
119
+ };
120
+ const getStudentGGBOptions = (identifiers) => {
121
+ const { triangleIds1, triangleIds2 } = identifiers;
122
+ const [triangle1, triangle2] = [triangleIds1, triangleIds2].map((triangleIds) => TriangleConstructor.fromIdentifiers(triangleIds));
123
+ const ggb = new GeogebraConstructor({
124
+ hideAxes: true,
125
+ isGridSimple: true,
126
+ customToolBar: toolBarConstructor({ point: true, segment: true }),
127
+ commands: [
128
+ //triangles
129
+ ...triangle1.commands,
130
+ //base segment
131
+ ...triangle2.sides[2].toGGBCommands(true),
132
+ `SetColor(${triangle2.sides[2].ggbName}, "${orange}")`,
133
+ ],
134
+ fontSize: 16,
135
+ });
136
+ return ggb.getOptions({
137
+ coords: ggb.getCoordsForPoints([...triangle1.points, ...triangle2.points]),
138
+ });
139
+ };
140
+ const getAnswerSegments = (identifiers) => {
141
+ const { triangleIds1, triangleIds2 } = identifiers;
142
+ const [_, triangle2] = [triangleIds1, triangleIds2].map((triangleIds) => TriangleConstructor.fromIdentifiers(triangleIds));
143
+ return [triangle2.sides[0], triangle2.sides[1]];
144
+ };
145
+ const getGGBAnswer = (identifiers) => {
146
+ return [
147
+ //answer segments
148
+ ...getAnswerSegments(identifiers).flatMap((segment) => [
149
+ ...segment.toGGBCommands(true),
150
+ `SetColor(${segment.ggbName}, "${greenMain}")`,
151
+ ]),
152
+ ];
153
+ };
154
+ const isGGBAnswerValid = (ans, { ggbAnswer, ...identifiers }) => {
155
+ const { triangleIds1, triangleIds2 } = identifiers;
156
+ const [triangle1, triangle2] = [triangleIds1, triangleIds2].map((triangleIds) => TriangleConstructor.fromIdentifiers(triangleIds));
157
+ const studentCommands = ans;
158
+ function getStudentPointsDictFromStudentCommands(commands) {
159
+ const regexPoint = new RegExp(`(?<name>\\w+)\\s?=\\s?\\((?<strX>-?\\d+(\\.\\d+)?),\\s?(?<strY>-?\\d+(\\.\\d+)?)\\)`);
160
+ const pointsDict = commands.reduce((acc, command) => {
161
+ const match = command.match(regexPoint);
162
+ if (match && match.groups) {
163
+ const { name, strX, strY } = match.groups;
164
+ const [x, y] = [strX, strY].map((strZ) => parseFloat(strZ));
165
+ const point = new Point(name, x, y);
166
+ acc[name] = point;
167
+ }
168
+ return acc;
169
+ }, {});
170
+ return pointsDict;
171
+ }
172
+ function getStudentSegmentsDictFromStudentCommands(commands) {
173
+ const studentPointsDict = getStudentPointsDictFromStudentCommands(commands);
174
+ const allPointsDict = Object.assign({}, Object.fromEntries([...triangle1.points, ...triangle2.points].map((point) => [
175
+ point.name,
176
+ point,
177
+ ])), studentPointsDict);
178
+ const regexSegment = new RegExp(`(?<name>\\w+)\\s?=\\s?Segment\\[(?<namePointA>\\w+),\\s?(?<namePointB>\\w+)\\]`);
179
+ const segmentsDict = studentCommands.reduce((acc, command) => {
180
+ const match = command.match(regexSegment);
181
+ if (match && match.groups) {
182
+ const { name, namePointA, namePointB } = match.groups;
183
+ const segment = new Segment(allPointsDict[namePointA], allPointsDict[namePointB]);
184
+ acc[name] = segment;
185
+ }
186
+ return acc;
187
+ }, {});
188
+ return segmentsDict;
189
+ }
190
+ const isSameSegment = (segment1, segment2) => {
191
+ return ((segment1.pointA.distanceTo(segment2.pointA) < 0.1 &&
192
+ segment1.pointB.distanceTo(segment2.pointB) < 0.1) ||
193
+ (segment1.pointB.distanceTo(segment2.pointA) < 0.1 &&
194
+ segment1.pointA.distanceTo(segment2.pointB) < 0.1));
195
+ };
196
+ const isSegmentsValid = (studentSegmentsDict) => {
197
+ const segmentsAns = Object.values(studentSegmentsDict);
198
+ const segmentsAnswer = getAnswerSegments(identifiers);
199
+ return ((isSameSegment(segmentsAns[0], segmentsAnswer[1]) &&
200
+ isSameSegment(segmentsAns[1], segmentsAnswer[0])) ||
201
+ (isSameSegment(segmentsAns[0], segmentsAnswer[0]) &&
202
+ isSameSegment(segmentsAns[1], segmentsAnswer[1])));
203
+ };
204
+ const studentSegmentsDict = getStudentSegmentsDictFromStudentCommands(studentCommands);
205
+ const isStudentSegmentsDictValid = (studentSegmentsDict) => Object.keys(studentSegmentsDict).length === 2;
206
+ return (isStudentSegmentsDictValid(studentSegmentsDict) &&
207
+ isSegmentsValid(studentSegmentsDict));
208
+ };
209
+ const getPlaceSegmentsOfSimilarTriangleQuestion = () => {
210
+ function createRandomGridTriangle(pointNames, point1) {
211
+ const baseX = randint(2, 11);
212
+ const point2 = new Point(pointNames[1], point1.x.evaluate() - baseX, point1.y.evaluate());
213
+ const midX = round((point1.x.evaluate() + point2.x.evaluate()) / 2.0, 0);
214
+ const offsetFromMidX = round(baseX * randfloat(-2, 2), 0);
215
+ const x3Candidate = midX + offsetFromMidX;
216
+ const point3 = new Point(pointNames[2], x3Candidate !== midX ? x3Candidate : midX + 1, point1.y.evaluate() + Math.max(1, round(baseX * randfloat(0, 2), 0)));
217
+ return new Triangle([point1, point2, point3]);
218
+ }
219
+ function createRandomIdentifiers() {
220
+ const [A, B, C, D, E, F] = randomMany("ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""), 6);
221
+ const point1 = new Point(A, -5, 0);
222
+ const triangle1 = createRandomGridTriangle([A, B, C], point1);
223
+ const vec1 = VectorConstructor.fromPoints(triangle1.points[0], triangle1.points[1]);
224
+ const vec2 = VectorConstructor.fromPoints(triangle1.points[0], triangle1.points[2]);
225
+ const factorNode = getRandomFactorNodeForVectors([vec1, vec2]).simplify();
226
+ const vec1Flipped = new Vector("vec1F", opposite(vec1.x), vec1.y);
227
+ const vec2Flipped = new Vector("vec2F", opposite(vec2.x), vec2.y);
228
+ const pointE = new Point(D, point1.x.evaluate() + 2, point1.y.evaluate());
229
+ const pointD = vec1Flipped.times(factorNode).getEndPoint(pointE, E);
230
+ const pointF = vec2Flipped.times(factorNode).getEndPoint(pointE, F);
231
+ const triangle2 = new Triangle([pointD, pointE, pointF]);
232
+ return {
233
+ triangleIds1: triangle1.toIdentifiers(),
234
+ triangleIds2: triangle2.toIdentifiers(),
235
+ factor: factorNode.toIdentifiers(),
236
+ };
237
+ }
238
+ function isSmallCoords(identifiers) {
239
+ const { triangleIds1, triangleIds2 } = identifiers;
240
+ const [triangle1, triangle2] = [triangleIds1, triangleIds2].map((triangleIds) => TriangleConstructor.fromIdentifiers(triangleIds));
241
+ const { xMin, xMax, yMin, yMax } = getCoordsForPoints([
242
+ ...triangle1.points,
243
+ ...triangle2.points,
244
+ ]);
245
+ return xMax - xMin < 15 && yMax - yMin < 15;
246
+ }
247
+ let identifiers;
248
+ let counter = -1;
249
+ let isValidIdentifiers = false;
250
+ while (!isValidIdentifiers && counter < 200) {
251
+ counter++;
252
+ identifiers = createRandomIdentifiers();
253
+ isValidIdentifiers = (() => {
254
+ if (counter < 100) {
255
+ const factorNode = NodeConstructor.fromIdentifiers(identifiers.factor);
256
+ const isIntegerFactor = () => factorNode.evaluate() % 1 === 0;
257
+ return !isIntegerFactor() && isSmallCoords(identifiers);
258
+ }
259
+ else {
260
+ return isSmallCoords(identifiers);
261
+ }
262
+ })();
263
+ }
264
+ if (!isValidIdentifiers) {
265
+ const triangle1 = new Triangle([
266
+ new Point("A", -5, 0),
267
+ new Point("B", -7, 0),
268
+ new Point("C", -7, 2),
269
+ ]);
270
+ const triangle2 = new Triangle([
271
+ new Point("D", -2, 0),
272
+ new Point("E", -3, 0),
273
+ new Point("F", -3, 1),
274
+ ]);
275
+ const defaultIdentifiers = {
276
+ triangleIds1: triangle1.toIdentifiers(),
277
+ triangleIds2: triangle2.toIdentifiers(),
278
+ factor: (2).toTree().toIdentifiers(),
279
+ };
280
+ identifiers = defaultIdentifiers;
281
+ }
282
+ return getQuestionFromIdentifiers(identifiers);
283
+ };
284
+ const getQuestionFromIdentifiers = (identifiers) => {
285
+ const question = {
286
+ ggbAnswer: getGGBAnswer(identifiers),
287
+ instruction: getInstruction(identifiers),
288
+ studentGgbOptions: getStudentGGBOptions(identifiers),
289
+ identifiers,
290
+ hint: getHint(identifiers),
291
+ correction: getCorrection(identifiers),
292
+ correctionGgbOptions: getCorrectionGGBOptions(identifiers),
293
+ };
294
+ return question;
295
+ };
296
+ export const placeSegmentsOfSimilarTriangle = {
297
+ id: "placeSegmentsOfSimilarTriangle",
298
+ label: "Tracer un triangle semblable sur une grille",
299
+ isSingleStep: true,
300
+ generator: (nb) => getDistinctQuestions(() => getPlaceSegmentsOfSimilarTriangleQuestion(), nb),
301
+ ggbTimer: 60,
302
+ isGGBAnswerValid,
303
+ subject: "Mathématiques",
304
+ getHint,
305
+ getCorrection,
306
+ getGGBAnswer,
307
+ getStudentGGBOptions,
308
+ answerType: "GGB",
309
+ getQuestionFromIdentifiers,
310
+ hasHintAndCorrection: true,
311
+ };