math-exercises 3.0.55 → 3.0.56
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.
- package/lib/exercises/math/calcul/arithmetics/index.d.ts +1 -0
- package/lib/exercises/math/calcul/arithmetics/index.d.ts.map +1 -1
- package/lib/exercises/math/calcul/arithmetics/index.js +1 -0
- package/lib/exercises/math/calcul/arithmetics/ppcmCalcul.d.ts +8 -0
- package/lib/exercises/math/calcul/arithmetics/ppcmCalcul.d.ts.map +1 -0
- package/lib/exercises/math/calcul/arithmetics/ppcmCalcul.js +87 -0
- package/lib/exercises/math/calcul/proportionality/proportionalityTable.d.ts.map +1 -1
- package/lib/exercises/math/calcul/proportionality/proportionalityTable.js +2 -2
- package/lib/exercises/math/calculLitteral/equation/binomialsTrinomialsProposedSolutions.d.ts.map +1 -1
- package/lib/exercises/math/calculLitteral/equation/binomialsTrinomialsProposedSolutions.js +7 -1
- package/lib/exercises/math/functions/basics/imageFunctionGeogebra.d.ts.map +1 -1
- package/lib/exercises/math/functions/basics/imageFunctionGeogebra.js +16 -0
- package/lib/exercises/math/geometry/areas/triangleArea.d.ts.map +1 -1
- package/lib/exercises/math/geometry/areas/triangleArea.js +34 -2
- package/lib/exercises/math/geometry/areas/triangleAreaV2.d.ts.map +1 -1
- package/lib/exercises/math/geometry/areas/triangleAreaV2.js +54 -8
- package/lib/exercises/math/geometry/cartesian/readAbscissOnLine.d.ts.map +1 -1
- package/lib/exercises/math/geometry/cartesian/readAbscissOnLine.js +29 -1
- package/lib/exercises/math/geometry/cartesian/readAbscissOnSemiLine.d.ts.map +1 -1
- package/lib/exercises/math/geometry/cartesian/readAbscissOnSemiLine.js +25 -1
- package/lib/exercises/math/geometry/lines/directorVectorFromAnother.d.ts.map +1 -1
- package/lib/exercises/math/geometry/lines/directorVectorFromAnother.js +1 -0
- package/lib/exercises/math/geometry/lines/index.d.ts +1 -0
- package/lib/exercises/math/geometry/lines/index.d.ts.map +1 -1
- package/lib/exercises/math/geometry/lines/index.js +1 -0
- package/lib/exercises/math/geometry/vectors/findCoordForAligment.d.ts +6 -0
- package/lib/exercises/math/geometry/vectors/findCoordForAligment.d.ts.map +1 -1
- package/lib/exercises/math/geometry/vectors/findCoordForAligment.js +161 -92
- package/lib/exercises/math/geometry/vectors/index.d.ts +1 -0
- package/lib/exercises/math/geometry/vectors/index.d.ts.map +1 -1
- package/lib/exercises/math/geometry/vectors/index.js +1 -0
- package/lib/exercises/math/geometry/volumes/coneVolume.d.ts.map +1 -1
- package/lib/exercises/math/geometry/volumes/coneVolume.js +68 -6
- package/lib/exercises/math/geometry/volumes/parallelepipedVolume.d.ts.map +1 -1
- package/lib/exercises/math/geometry/volumes/parallelepipedVolume.js +55 -11
- package/lib/exercises/math/geometry/volumes/sphereVolume.d.ts.map +1 -1
- package/lib/exercises/math/geometry/volumes/sphereVolume.js +31 -3
- package/lib/exercises/math/geometry/volumes/volumeOfCube.d.ts.map +1 -1
- package/lib/exercises/math/geometry/volumes/volumeOfCube.js +46 -18
- package/lib/exercises/math/geometry/volumes/volumeOfPyramidWithSquareOrRectBase.d.ts.map +1 -1
- package/lib/exercises/math/geometry/volumes/volumeOfPyramidWithSquareOrRectBase.js +114 -63
- package/lib/exercises/math/geometry/volumes/volumeOfPyramidWithTriangleBase.d.ts.map +1 -1
- package/lib/exercises/math/geometry/volumes/volumeOfPyramidWithTriangleBase.js +102 -64
- package/lib/exercises/math/geometry/volumes/volumeOfPyramidWithTriangleRectBase.d.ts.map +1 -1
- package/lib/exercises/math/geometry/volumes/volumeOfPyramidWithTriangleRectBase.js +99 -53
- package/lib/exercises/math/sequences/geometric/geometricFirstTermsGeneralSum.d.ts.map +1 -1
- package/lib/exercises/math/sequences/geometric/geometricFirstTermsGeneralSum.js +12 -3
- package/lib/exercises/math/trigonometry/remarkableValues.d.ts.map +1 -1
- package/lib/exercises/math/trigonometry/remarkableValues.js +8 -0
- package/lib/index.d.ts +8 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/math/geometry/vector.d.ts +2 -0
- package/lib/math/geometry/vector.d.ts.map +1 -1
- package/lib/math/geometry/vector.js +6 -0
- package/lib/math/utils/arithmetic/lcm.d.ts +2 -0
- package/lib/math/utils/arithmetic/lcm.d.ts.map +1 -0
- package/lib/math/utils/arithmetic/lcm.js +5 -0
- package/lib/playground.d.ts.map +1 -1
- package/lib/playground.js +33 -0
- package/lib/tree/nodes/operators/fractionNode.d.ts +2 -2
- package/lib/tree/nodes/operators/fractionNode.d.ts.map +1 -1
- package/lib/tree/nodes/operators/fractionNode.js +6 -6
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"volumeOfPyramidWithSquareOrRectBase.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/volumes/volumeOfPyramidWithSquareOrRectBase.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,
|
|
1
|
+
{"version":3,"file":"volumeOfPyramidWithSquareOrRectBase.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/volumes/volumeOfPyramidWithSquareOrRectBase.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAeT,MAAM,6BAA6B,CAAC;AAoBrC,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,aAAa,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,KAAK,OAAO,GAAG;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB,CAAC;AAkNF,eAAO,MAAM,mCAAmC,EAAE,QAAQ,CAAC,WAAW,CAcrE,CAAC"}
|
|
@@ -3,36 +3,136 @@ import { getDistinctQuestions } from "../../../../exercises/utils/getDistinctQue
|
|
|
3
3
|
import { GeogebraConstructor } from "../../../../geogebra/geogebraConstructor.js";
|
|
4
4
|
import { RationalConstructor, } from "../../../../math/numbers/rationals/rational.js";
|
|
5
5
|
import { randint } from "../../../../math/utils/random/randint.js";
|
|
6
|
+
import { round } from "../../../../math/utils/round.js";
|
|
6
7
|
import { isNumberNode } from "../../../../tree/nodes/numbers/numberNode.js";
|
|
7
8
|
import { FractionNode } from "../../../../tree/nodes/operators/fractionNode.js";
|
|
8
|
-
import { MultiplyNode } from "../../../../tree/nodes/operators/multiplyNode.js";
|
|
9
|
+
import { multiply, MultiplyNode, } from "../../../../tree/nodes/operators/multiplyNode.js";
|
|
10
|
+
import { square } from "../../../../tree/nodes/operators/powerNode.js";
|
|
9
11
|
import { random } from "../../../../utils/alea/random.js";
|
|
12
|
+
import { alignTex } from "../../../../utils/latex/alignTex.js";
|
|
10
13
|
const polygonTypes = ["Square", "Rectangular"];
|
|
11
14
|
const getVolumeOfPyramidWithSquareOrRectBaseQuestion = () => {
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
+
const h = randint(1, 11);
|
|
16
|
+
const polygonType = random(polygonTypes);
|
|
17
|
+
let sideOne = 0;
|
|
18
|
+
let sideTwo = 0;
|
|
19
|
+
switch (polygonType) {
|
|
20
|
+
case "Square":
|
|
21
|
+
const randomSide = randint(1, 10);
|
|
22
|
+
sideOne = randomSide;
|
|
23
|
+
sideTwo = randomSide;
|
|
24
|
+
break;
|
|
25
|
+
case "Rectangular":
|
|
26
|
+
sideOne = randint(1, 11);
|
|
27
|
+
sideTwo = randint(1, 11, [sideOne]);
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
const identifiers = {
|
|
31
|
+
h,
|
|
32
|
+
baseOfPyramid: { sideSizes: [sideOne, sideTwo], type: polygonType },
|
|
33
|
+
};
|
|
34
|
+
return getQuestionFromIdentifiers(identifiers);
|
|
35
|
+
};
|
|
36
|
+
const getGGBOptions = (identifiers) => {
|
|
37
|
+
const { baseOfPyramid, h } = identifiers;
|
|
38
|
+
const { sideSizes, type } = baseOfPyramid;
|
|
39
|
+
const [sideOne, sideTwo] = sideSizes;
|
|
40
|
+
let commands = [
|
|
41
|
+
`A=Point({0,0,0})`,
|
|
42
|
+
`B=Point({${sideOne},0,0})`,
|
|
43
|
+
`C=Point({${sideOne},${sideTwo},0})`,
|
|
44
|
+
`D=Point({0,${sideTwo},0})`,
|
|
45
|
+
`ShowLabel(A,true)`,
|
|
46
|
+
`ShowLabel(B,true)`,
|
|
47
|
+
`ShowLabel(C,true)`,
|
|
48
|
+
`ShowLabel(D,true)`,
|
|
49
|
+
`SetFixed(A,true)`,
|
|
50
|
+
`SetFixed(B,true)`,
|
|
51
|
+
`SetFixed(C,true)`,
|
|
52
|
+
`SetFixed(D,true)`,
|
|
53
|
+
`Poly=Polygon(A,B,C,D)`,
|
|
54
|
+
];
|
|
55
|
+
commands = commands.concat([
|
|
56
|
+
`H=Point({${sideSizes[0] / 2},${sideSizes[1] / 2},${h}})`,
|
|
57
|
+
`SetFixed(H,true)`,
|
|
58
|
+
`ShowLabel(H,true)`,
|
|
59
|
+
`Pyra=Pyramid(Poly,H)`,
|
|
60
|
+
]);
|
|
15
61
|
const ggb = new GeogebraConstructor({
|
|
16
62
|
commands,
|
|
17
63
|
hideAxes: true,
|
|
18
64
|
hideGrid: true,
|
|
19
65
|
is3D: true,
|
|
20
66
|
});
|
|
21
|
-
const
|
|
67
|
+
const maxCoord = Math.max(baseOfPyramid.sideSizes[0], baseOfPyramid.sideSizes[1]);
|
|
68
|
+
return ggb.getOptions({
|
|
69
|
+
coords: [-2, maxCoord + 1, -2, maxCoord + 1, -2, h + 1],
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
const getInstruction = (identifiers) => {
|
|
73
|
+
const { baseOfPyramid, h } = identifiers;
|
|
22
74
|
const instruction = `$ABCDH$ est une pyramide à base ${getPolygonNameInFr(baseOfPyramid.type)} de hauteur $${h}$. Calculer son volume en sachant que : ${baseOfPyramid.type === "Square"
|
|
23
75
|
? `$AB=${baseOfPyramid.sideSizes[0]}$`
|
|
24
76
|
: `$AB=${baseOfPyramid.sideSizes[0]}$ et $BC=${baseOfPyramid.sideSizes[1]}$`}.`;
|
|
77
|
+
return instruction;
|
|
78
|
+
};
|
|
79
|
+
const getAnswer = (identifiers) => {
|
|
80
|
+
const { baseOfPyramid, h } = identifiers;
|
|
25
81
|
const volume = calculateVolume(baseOfPyramid.sideSizes, h).simplify();
|
|
26
|
-
|
|
82
|
+
return volume.toTex();
|
|
83
|
+
};
|
|
84
|
+
const getHint = (identifiers) => {
|
|
85
|
+
const { baseOfPyramid, h } = identifiers;
|
|
86
|
+
const { sideSizes, type } = baseOfPyramid;
|
|
87
|
+
const baseShape = type === "Square" ? "carré" : "rectangle";
|
|
88
|
+
return `Le volume d'une pyramide est donné par la formule :
|
|
89
|
+
|
|
90
|
+
$$
|
|
91
|
+
V = \\frac{1}{3} \\times \\text{aire de la base} \\times \\text{hauteur}
|
|
92
|
+
$$
|
|
93
|
+
|
|
94
|
+
La base de la pyramide est ici un ${baseShape}. Il faut donc commencer par calculer son aire.`;
|
|
95
|
+
};
|
|
96
|
+
const getCorrection = (identifiers) => {
|
|
97
|
+
const { baseOfPyramid, h } = identifiers;
|
|
98
|
+
const { sideSizes, type } = baseOfPyramid;
|
|
99
|
+
const baseShape = type === "Square" ? "carré" : "rectangle";
|
|
100
|
+
const isSquare = type === "Square";
|
|
101
|
+
const aera = round(isSquare ? sideSizes[0] ** 2 : sideSizes[0] * sideSizes[1], 2).frenchify();
|
|
102
|
+
return `Le volume d'une pyramide est donné par la formule :
|
|
103
|
+
|
|
104
|
+
$$
|
|
105
|
+
V = \\frac{1}{3} \\times \\text{aire de la base} \\times \\text{hauteur}
|
|
106
|
+
$$
|
|
107
|
+
|
|
108
|
+
Ici, la base est un ${baseShape}. Son aire est donc égale à :
|
|
109
|
+
|
|
110
|
+
$$
|
|
111
|
+
${isSquare
|
|
112
|
+
? square(sideSizes[0]).toTex()
|
|
113
|
+
: multiply(sideSizes[0], sideSizes[1]).toTex({
|
|
114
|
+
forceNoSimplification: true,
|
|
115
|
+
})} = ${aera}
|
|
116
|
+
$$
|
|
117
|
+
|
|
118
|
+
Le volume de la pyramide est donc :
|
|
119
|
+
|
|
120
|
+
${alignTex([
|
|
121
|
+
["V", "=", `\\frac{1}{3}\\times ${aera} \\times ${h}`],
|
|
122
|
+
["", "=", getAnswer(identifiers)],
|
|
123
|
+
])}
|
|
124
|
+
`;
|
|
125
|
+
};
|
|
126
|
+
const getQuestionFromIdentifiers = (identifiers) => {
|
|
27
127
|
const question = {
|
|
28
|
-
answer:
|
|
29
|
-
instruction:
|
|
128
|
+
answer: getAnswer(identifiers),
|
|
129
|
+
instruction: getInstruction(identifiers),
|
|
30
130
|
keys: [],
|
|
31
131
|
answerFormat: "tex",
|
|
32
|
-
ggbOptions:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
132
|
+
ggbOptions: getGGBOptions(identifiers),
|
|
133
|
+
identifiers,
|
|
134
|
+
hint: getHint(identifiers),
|
|
135
|
+
correction: getCorrection(identifiers),
|
|
36
136
|
};
|
|
37
137
|
return question;
|
|
38
138
|
};
|
|
@@ -63,58 +163,9 @@ const generatePropositions = (baseOfPyramid, h) => {
|
|
|
63
163
|
.toTex();
|
|
64
164
|
return [firstProposition, secondProposition];
|
|
65
165
|
};
|
|
66
|
-
const generateExercise = () => {
|
|
67
|
-
const h = randint(1, 11);
|
|
68
|
-
const polygonType = random(polygonTypes);
|
|
69
|
-
const base = generatePolygonWithGgbCmnds(polygonType);
|
|
70
|
-
const ggbCommands = base.commands.concat([
|
|
71
|
-
`H=Point({${base.sideSizes[0] / 2},${base.sideSizes[1] / 2},${h}})`,
|
|
72
|
-
`SetFixed(H,true)`,
|
|
73
|
-
`ShowLabel(H,true)`,
|
|
74
|
-
`Pyra=Pyramid(Poly,H)`,
|
|
75
|
-
]);
|
|
76
|
-
return {
|
|
77
|
-
ggbCommands,
|
|
78
|
-
h,
|
|
79
|
-
baseOfPyramid: { sideSizes: base.sideSizes, type: polygonType },
|
|
80
|
-
};
|
|
81
|
-
};
|
|
82
166
|
const calculateVolume = (baseOfPyramidSides, h) => {
|
|
83
167
|
return new MultiplyNode(new FractionNode((1).toTree(), (3).toTree()), (baseOfPyramidSides[0] * baseOfPyramidSides[1] * h).toTree());
|
|
84
168
|
};
|
|
85
|
-
const generatePolygonWithGgbCmnds = (polygonType) => {
|
|
86
|
-
let sideOne = 0;
|
|
87
|
-
let sideTwo = 0;
|
|
88
|
-
switch (polygonType) {
|
|
89
|
-
case "Square":
|
|
90
|
-
const randomSide = randint(1, 10);
|
|
91
|
-
sideOne = randomSide;
|
|
92
|
-
sideTwo = randomSide;
|
|
93
|
-
break;
|
|
94
|
-
case "Rectangular":
|
|
95
|
-
sideOne = randint(1, 11);
|
|
96
|
-
sideTwo = randint(1, 11, [sideOne]);
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
return {
|
|
100
|
-
commands: [
|
|
101
|
-
`A=Point({0,0,0})`,
|
|
102
|
-
`B=Point({${sideOne},0,0})`,
|
|
103
|
-
`C=Point({${sideOne},${sideTwo},0})`,
|
|
104
|
-
`D=Point({0,${sideTwo},0})`,
|
|
105
|
-
`ShowLabel(A,true)`,
|
|
106
|
-
`ShowLabel(B,true)`,
|
|
107
|
-
`ShowLabel(C,true)`,
|
|
108
|
-
`ShowLabel(D,true)`,
|
|
109
|
-
`SetFixed(A,true)`,
|
|
110
|
-
`SetFixed(B,true)`,
|
|
111
|
-
`SetFixed(C,true)`,
|
|
112
|
-
`SetFixed(D,true)`,
|
|
113
|
-
`Poly=Polygon(A,B,C,D)`,
|
|
114
|
-
],
|
|
115
|
-
sideSizes: [sideOne, sideTwo],
|
|
116
|
-
};
|
|
117
|
-
};
|
|
118
169
|
const getPolygonNameInFr = (polygonType) => {
|
|
119
170
|
switch (polygonType) {
|
|
120
171
|
case "Square":
|
|
@@ -128,9 +179,7 @@ const getPolygonNameInFr = (polygonType) => {
|
|
|
128
179
|
export const volumeOfPyramidWithSquareOrRectBase = {
|
|
129
180
|
id: "volumeOfPyramidWithSquareOrRectBase",
|
|
130
181
|
label: "Calculer le volume d'une pyramide à base carrée ou rectangulaire",
|
|
131
|
-
levels: ["2nde"],
|
|
132
182
|
isSingleStep: true,
|
|
133
|
-
sections: ["Géométrie euclidienne"],
|
|
134
183
|
generator: (nb) => getDistinctQuestions(getVolumeOfPyramidWithSquareOrRectBaseQuestion, nb),
|
|
135
184
|
qcmTimer: 60,
|
|
136
185
|
freeTimer: 60,
|
|
@@ -138,4 +187,6 @@ export const volumeOfPyramidWithSquareOrRectBase = {
|
|
|
138
187
|
isAnswerValid,
|
|
139
188
|
hasGeogebra: true,
|
|
140
189
|
subject: "Mathématiques",
|
|
190
|
+
getQuestionFromIdentifiers,
|
|
191
|
+
hasHintAndCorrection: true,
|
|
141
192
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"volumeOfPyramidWithTriangleBase.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/volumes/volumeOfPyramidWithTriangleBase.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,
|
|
1
|
+
{"version":3,"file":"volumeOfPyramidWithTriangleBase.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/volumes/volumeOfPyramidWithTriangleBase.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAeT,MAAM,6BAA6B,CAAC;AAgBrC,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,kBAAkB,EAAE,aAAa,CAAC;CACnC,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AA0MF,eAAO,MAAM,+BAA+B,EAAE,QAAQ,CAAC,WAAW,CAcjE,CAAC"}
|
|
@@ -3,10 +3,12 @@ import { getDistinctQuestions } from "../../../../exercises/utils/getDistinctQue
|
|
|
3
3
|
import { GeogebraConstructor } from "../../../../geogebra/geogebraConstructor.js";
|
|
4
4
|
import { RationalConstructor } from "../../../../math/numbers/rationals/rational.js";
|
|
5
5
|
import { randint } from "../../../../math/utils/random/randint.js";
|
|
6
|
+
import { round } from "../../../../math/utils/round.js";
|
|
6
7
|
import { isNumberNode } from "../../../../tree/nodes/numbers/numberNode.js";
|
|
7
|
-
import { FractionNode } from "../../../../tree/nodes/operators/fractionNode.js";
|
|
8
|
-
import { MultiplyNode } from "../../../../tree/nodes/operators/multiplyNode.js";
|
|
8
|
+
import { frac, FractionNode } from "../../../../tree/nodes/operators/fractionNode.js";
|
|
9
|
+
import { multiply, MultiplyNode, } from "../../../../tree/nodes/operators/multiplyNode.js";
|
|
9
10
|
import { random } from "../../../../utils/alea/random.js";
|
|
11
|
+
import { alignTex } from "../../../../utils/latex/alignTex.js";
|
|
10
12
|
const pythagoreTriplet = [
|
|
11
13
|
[5, 12, 13],
|
|
12
14
|
[8, 15, 17],
|
|
@@ -19,10 +21,91 @@ const pythagoreTriplet = [
|
|
|
19
21
|
[16, 63, 65],
|
|
20
22
|
];
|
|
21
23
|
const getVolumeOfPyramidWithTriangleBaseQuestion = () => {
|
|
22
|
-
const exercise = generateExercise();
|
|
23
|
-
const
|
|
24
|
-
const baseOfPyramidSides = exercise.baseOfPyramidSides;
|
|
25
|
-
const
|
|
24
|
+
// const exercise = generateExercise();
|
|
25
|
+
const h = randint(3, 21);
|
|
26
|
+
// const baseOfPyramidSides = exercise.baseOfPyramidSides;
|
|
27
|
+
const rectTriangle = random(pythagoreTriplet);
|
|
28
|
+
const ABSide = rectTriangle[0];
|
|
29
|
+
const ACSide = rectTriangle[1];
|
|
30
|
+
const BCSide = rectTriangle[2];
|
|
31
|
+
const identifiers = { h, baseOfPyramidSides: { ABSide, ACSide, BCSide } };
|
|
32
|
+
return getQuestionFromIdentifiers(identifiers);
|
|
33
|
+
};
|
|
34
|
+
const getInstruction = (identifiers) => {
|
|
35
|
+
const { baseOfPyramidSides, h } = identifiers;
|
|
36
|
+
return `$ABCH$ est une pyramide à base triangulaire de hauteur $${h}$. Le point $D$ est le pied de la hauteur issue de $C$ dans le triangle $ABC$.
|
|
37
|
+
|
|
38
|
+
Calculer le volume de la pyramide en sachant que $AB=${baseOfPyramidSides.ABSide}$ et $CD=${baseOfPyramidSides.ACSide}$.`;
|
|
39
|
+
};
|
|
40
|
+
const getAnswer = (identifiers) => {
|
|
41
|
+
const { baseOfPyramidSides, h } = identifiers;
|
|
42
|
+
const volume = calculateVolume(baseOfPyramidSides, h);
|
|
43
|
+
return volume.simplify().toTex();
|
|
44
|
+
};
|
|
45
|
+
const getHint = (identifiers) => {
|
|
46
|
+
return `Le volume d'une pyramide est donné par la formule :
|
|
47
|
+
|
|
48
|
+
$$
|
|
49
|
+
V = \\frac{1}{3} \\times \\text{aire de la base} \\times \\text{hauteur}
|
|
50
|
+
$$
|
|
51
|
+
|
|
52
|
+
La base de la pyramide est ici un triangle. Son aire se calcule par la formule :
|
|
53
|
+
|
|
54
|
+
$$
|
|
55
|
+
A = \\frac{\\text{base}\\times\\text{hauteur}}{2}
|
|
56
|
+
$$`;
|
|
57
|
+
};
|
|
58
|
+
const getCorrection = (identifiers) => {
|
|
59
|
+
const { h, baseOfPyramidSides } = identifiers;
|
|
60
|
+
const { ABSide, ACSide, BCSide } = baseOfPyramidSides;
|
|
61
|
+
const aera = round((ABSide * ACSide) / 2, 2).frenchify();
|
|
62
|
+
return `Le volume d'une pyramide est donné par la formule :
|
|
63
|
+
|
|
64
|
+
$$
|
|
65
|
+
V = \\frac{1}{3} \\times \\text{aire de la base} \\times \\text{hauteur}
|
|
66
|
+
$$
|
|
67
|
+
|
|
68
|
+
Ici, la base est un triangle rectangle dont une hauteur est $${ACSide}$ et sa base associée vaut $${ABSide}$. Son aire est donc égale à :
|
|
69
|
+
|
|
70
|
+
$$
|
|
71
|
+
${frac(multiply(ACSide, ABSide), 2).toTex()} = ${aera}
|
|
72
|
+
$$
|
|
73
|
+
|
|
74
|
+
Le volume de la pyramide est donc :
|
|
75
|
+
|
|
76
|
+
${alignTex([
|
|
77
|
+
["V", "=", `\\frac{1}{3}\\times ${aera} \\times ${h}`],
|
|
78
|
+
["", "=", getAnswer(identifiers)],
|
|
79
|
+
])}
|
|
80
|
+
`;
|
|
81
|
+
};
|
|
82
|
+
const getGGBOptions = (identifiers) => {
|
|
83
|
+
const { baseOfPyramidSides, h } = identifiers;
|
|
84
|
+
const { ABSide, ACSide, BCSide } = baseOfPyramidSides;
|
|
85
|
+
// const triangle = generateTriangleWithGGBCommands();
|
|
86
|
+
//!!!!!!!!!!!
|
|
87
|
+
const originX = randint(-ABSide + 4, -2);
|
|
88
|
+
let commands = [
|
|
89
|
+
`A=Point({${originX},0,0})`,
|
|
90
|
+
`B=Point({${ABSide + originX},0,0})`,
|
|
91
|
+
`C=Point({0,${ACSide},0})`,
|
|
92
|
+
`ShowLabel(A,True)`,
|
|
93
|
+
`ShowLabel(B,True)`,
|
|
94
|
+
`ShowLabel(C,True)`,
|
|
95
|
+
`SetFixed(A,true)`,
|
|
96
|
+
`SetFixed(B,true)`,
|
|
97
|
+
`SetFixed(C,true)`,
|
|
98
|
+
`Poly=Polygon(A,B,C)`,
|
|
99
|
+
];
|
|
100
|
+
commands = commands.concat([
|
|
101
|
+
`H=Point({0,${ACSide / 4},${h}})`,
|
|
102
|
+
`D=Point({0,0,0})`,
|
|
103
|
+
`ShowLabel(D,true)`,
|
|
104
|
+
`ShowLabel(H,true)`,
|
|
105
|
+
`SetFixed(H,true)`,
|
|
106
|
+
`SetFixed(D,true)`,
|
|
107
|
+
`Pyra=Pyramid(Poly,H)`,
|
|
108
|
+
]);
|
|
26
109
|
const ggb = new GeogebraConstructor({
|
|
27
110
|
commands,
|
|
28
111
|
hideAxes: true,
|
|
@@ -30,23 +113,20 @@ const getVolumeOfPyramidWithTriangleBaseQuestion = () => {
|
|
|
30
113
|
is3D: true,
|
|
31
114
|
});
|
|
32
115
|
const maxCoord = Math.max(baseOfPyramidSides.ABSide, baseOfPyramidSides.ACSide);
|
|
116
|
+
return ggb.getOptions({
|
|
117
|
+
coords: [originX, maxCoord + 1, -2, maxCoord + 1, -2, h + 1],
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
const getQuestionFromIdentifiers = (identifiers) => {
|
|
33
121
|
const question = {
|
|
34
|
-
answer:
|
|
35
|
-
instruction:
|
|
36
|
-
Calculer le volume de la pyramide en sachant que $AB=${baseOfPyramidSides.ABSide}$ et $CD=${baseOfPyramidSides.ACSide}$.`,
|
|
122
|
+
answer: getAnswer(identifiers),
|
|
123
|
+
instruction: getInstruction(identifiers),
|
|
37
124
|
keys: [],
|
|
38
125
|
answerFormat: "tex",
|
|
39
|
-
ggbOptions:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
-2,
|
|
44
|
-
maxCoord + 1,
|
|
45
|
-
-2,
|
|
46
|
-
exercise.h + 1,
|
|
47
|
-
],
|
|
48
|
-
}),
|
|
49
|
-
identifiers: { h: exercise.h, baseOfPyramidSides },
|
|
126
|
+
ggbOptions: getGGBOptions(identifiers),
|
|
127
|
+
identifiers,
|
|
128
|
+
hint: getHint(identifiers),
|
|
129
|
+
correction: getCorrection(identifiers),
|
|
50
130
|
};
|
|
51
131
|
return question;
|
|
52
132
|
};
|
|
@@ -83,54 +163,10 @@ const generatePropositions = (baseOfPyramidSides, h) => {
|
|
|
83
163
|
const calculateVolume = (sideSize, h) => {
|
|
84
164
|
return new FractionNode(new MultiplyNode(new FractionNode((sideSize.ABSide * sideSize.ACSide).toTree(), (2).toTree()), h.toTree()), (3).toTree());
|
|
85
165
|
};
|
|
86
|
-
const generateExercise = () => {
|
|
87
|
-
const h = randint(3, 21);
|
|
88
|
-
const triangle = generateTriangleWithGGBCommands();
|
|
89
|
-
const ggbCommands = triangle.commands.concat([
|
|
90
|
-
`H=Point({0,${triangle.sideSizes.ACSide / 4},${h}})`,
|
|
91
|
-
`D=Point({0,0,0})`,
|
|
92
|
-
`ShowLabel(D,true)`,
|
|
93
|
-
`ShowLabel(H,true)`,
|
|
94
|
-
`SetFixed(H,true)`,
|
|
95
|
-
`SetFixed(D,true)`,
|
|
96
|
-
`Pyra=Pyramid(Poly,H)`,
|
|
97
|
-
]);
|
|
98
|
-
return {
|
|
99
|
-
ggbCommands,
|
|
100
|
-
h,
|
|
101
|
-
baseOfPyramidSides: triangle.sideSizes,
|
|
102
|
-
originX: triangle.originX,
|
|
103
|
-
};
|
|
104
|
-
};
|
|
105
|
-
const generateTriangleWithGGBCommands = () => {
|
|
106
|
-
const rectTriangle = random(pythagoreTriplet);
|
|
107
|
-
const ABSide = rectTriangle[0];
|
|
108
|
-
const originX = randint(-ABSide + 4, -2);
|
|
109
|
-
const ACSide = rectTriangle[1];
|
|
110
|
-
const BCSide = rectTriangle[2];
|
|
111
|
-
return {
|
|
112
|
-
commands: [
|
|
113
|
-
`A=Point({${originX},0,0})`,
|
|
114
|
-
`B=Point({${ABSide + originX},0,0})`,
|
|
115
|
-
`C=Point({0,${ACSide},0})`,
|
|
116
|
-
`ShowLabel(A,True)`,
|
|
117
|
-
`ShowLabel(B,True)`,
|
|
118
|
-
`ShowLabel(C,True)`,
|
|
119
|
-
`SetFixed(A,true)`,
|
|
120
|
-
`SetFixed(B,true)`,
|
|
121
|
-
`SetFixed(C,true)`,
|
|
122
|
-
`Poly=Polygon(A,B,C)`,
|
|
123
|
-
],
|
|
124
|
-
sideSizes: { ABSide, ACSide, BCSide },
|
|
125
|
-
originX,
|
|
126
|
-
};
|
|
127
|
-
};
|
|
128
166
|
export const volumeOfPyramidWithTriangleBase = {
|
|
129
167
|
id: "volumeOfPyramidWithTriangleBase",
|
|
130
168
|
label: "Calculer le volume d'une pyramide à base triangulaire",
|
|
131
|
-
levels: ["2nde"],
|
|
132
169
|
isSingleStep: true,
|
|
133
|
-
sections: ["Géométrie euclidienne"],
|
|
134
170
|
generator: (nb) => getDistinctQuestions(getVolumeOfPyramidWithTriangleBaseQuestion, nb),
|
|
135
171
|
qcmTimer: 60,
|
|
136
172
|
freeTimer: 60,
|
|
@@ -138,4 +174,6 @@ export const volumeOfPyramidWithTriangleBase = {
|
|
|
138
174
|
isAnswerValid,
|
|
139
175
|
hasGeogebra: true,
|
|
140
176
|
subject: "Mathématiques",
|
|
177
|
+
getQuestionFromIdentifiers,
|
|
178
|
+
hasHintAndCorrection: true,
|
|
141
179
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"volumeOfPyramidWithTriangleRectBase.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/volumes/volumeOfPyramidWithTriangleRectBase.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,
|
|
1
|
+
{"version":3,"file":"volumeOfPyramidWithTriangleRectBase.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/geometry/volumes/volumeOfPyramidWithTriangleRectBase.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAeT,MAAM,6BAA6B,CAAC;AAiBrC,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,kBAAkB,EAAE,aAAa,CAAC;CACnC,CAAC;AAEF,KAAK,aAAa,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAyMxE,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,WAAW,CAejD,CAAC"}
|
|
@@ -3,10 +3,12 @@ import { getDistinctQuestions } from "../../../../exercises/utils/getDistinctQue
|
|
|
3
3
|
import { GeogebraConstructor } from "../../../../geogebra/geogebraConstructor.js";
|
|
4
4
|
import { RationalConstructor } from "../../../../math/numbers/rationals/rational.js";
|
|
5
5
|
import { randint } from "../../../../math/utils/random/randint.js";
|
|
6
|
+
import { round } from "../../../../math/utils/round.js";
|
|
6
7
|
import { isNumberNode } from "../../../../tree/nodes/numbers/numberNode.js";
|
|
7
|
-
import { FractionNode } from "../../../../tree/nodes/operators/fractionNode.js";
|
|
8
|
-
import { MultiplyNode } from "../../../../tree/nodes/operators/multiplyNode.js";
|
|
8
|
+
import { frac, FractionNode } from "../../../../tree/nodes/operators/fractionNode.js";
|
|
9
|
+
import { multiply, MultiplyNode, } from "../../../../tree/nodes/operators/multiplyNode.js";
|
|
9
10
|
import { random } from "../../../../utils/alea/random.js";
|
|
11
|
+
import { alignTex } from "../../../../utils/latex/alignTex.js";
|
|
10
12
|
const pythagoreTriplet = [
|
|
11
13
|
[3, 4, 5],
|
|
12
14
|
[5, 12, 13],
|
|
@@ -20,27 +22,108 @@ const pythagoreTriplet = [
|
|
|
20
22
|
[16, 63, 65],
|
|
21
23
|
];
|
|
22
24
|
const getVolumeOfPyramidWithTriangleRectBase = () => {
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const baseOfPyramidSides =
|
|
26
|
-
|
|
25
|
+
const h = randint(1, 11);
|
|
26
|
+
const values = random(pythagoreTriplet);
|
|
27
|
+
const baseOfPyramidSides = {
|
|
28
|
+
ABSide: values[0],
|
|
29
|
+
ACSide: values[1],
|
|
30
|
+
BCSide: values[2],
|
|
31
|
+
};
|
|
32
|
+
const identifiers = { h: h, baseOfPyramidSides };
|
|
33
|
+
return getQuestionFromIdentifiers(identifiers);
|
|
34
|
+
};
|
|
35
|
+
const getInstruction = (identifiers) => {
|
|
36
|
+
const { h, baseOfPyramidSides } = identifiers;
|
|
37
|
+
return `$ABCH$ est une pyramide à base triangulaire de hauteur $${h}$.
|
|
38
|
+
|
|
39
|
+
Calculer le volume de la pyramide en sachant que : $AB=${baseOfPyramidSides.ABSide}$, $AC=${baseOfPyramidSides.ACSide}$, $BC=${baseOfPyramidSides.BCSide}$ et $(AC)\\perp(AB)$.`;
|
|
40
|
+
};
|
|
41
|
+
const getAnswer = (identifiers) => {
|
|
42
|
+
const { h, baseOfPyramidSides } = identifiers;
|
|
43
|
+
const volume = calculateVolume(baseOfPyramidSides, h);
|
|
44
|
+
return volume.simplify().toTex();
|
|
45
|
+
};
|
|
46
|
+
const getGGBOptions = (identifiers) => {
|
|
47
|
+
const { h, baseOfPyramidSides } = identifiers;
|
|
48
|
+
const { ABSide, ACSide, BCSide } = baseOfPyramidSides;
|
|
49
|
+
let commands = [
|
|
50
|
+
`A=Point({0,0,0})`,
|
|
51
|
+
`B=Point({${ABSide},0,0})`,
|
|
52
|
+
`C=Point({0,${ACSide},0})`,
|
|
53
|
+
`ang=Angle(C,A,B)`,
|
|
54
|
+
`ShowLabel(ang,false)`,
|
|
55
|
+
`ShowLabel(A,True)`,
|
|
56
|
+
`ShowLabel(B,True)`,
|
|
57
|
+
`ShowLabel(C,True)`,
|
|
58
|
+
`SetFixed(A,true)`,
|
|
59
|
+
`SetFixed(B,true)`,
|
|
60
|
+
`SetFixed(C,true)`,
|
|
61
|
+
`Poly=Polygon(A,B,C)`,
|
|
62
|
+
];
|
|
63
|
+
commands = commands.concat([
|
|
64
|
+
`H=Point({${ABSide / 4},${ACSide / 4},${h}})`,
|
|
65
|
+
`SetFixed(H,true)`,
|
|
66
|
+
`ShowLabel(H,true)`,
|
|
67
|
+
`Pyra=Pyramid(Poly,H)`,
|
|
68
|
+
]);
|
|
27
69
|
const ggb = new GeogebraConstructor({
|
|
28
70
|
commands,
|
|
29
71
|
hideAxes: true,
|
|
30
72
|
hideGrid: true,
|
|
31
73
|
is3D: true,
|
|
32
74
|
});
|
|
33
|
-
const maxCoord = Math.max(
|
|
75
|
+
const maxCoord = Math.max(ABSide, ACSide);
|
|
76
|
+
return ggb.getOptions({
|
|
77
|
+
coords: [-2, maxCoord + 1, -2, maxCoord + 1, -2, h + 1],
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
const getHint = (identifiers) => {
|
|
81
|
+
return `Le volume d'une pyramide est donné par la formule :
|
|
82
|
+
|
|
83
|
+
$$
|
|
84
|
+
V = \\frac{1}{3} \\times \\text{aire de la base} \\times \\text{hauteur}
|
|
85
|
+
$$
|
|
86
|
+
|
|
87
|
+
La base de la pyramide est ici un triangle rectangle. Son aire se calcule par la formule :
|
|
88
|
+
|
|
89
|
+
$$
|
|
90
|
+
A = \\frac{\\text{base}\\times\\text{hauteur}}{2}
|
|
91
|
+
$$`;
|
|
92
|
+
};
|
|
93
|
+
const getCorrection = (identifiers) => {
|
|
94
|
+
const { h, baseOfPyramidSides } = identifiers;
|
|
95
|
+
const { ABSide, ACSide, BCSide } = baseOfPyramidSides;
|
|
96
|
+
const aera = round((ABSide * ACSide) / 2, 2).frenchify();
|
|
97
|
+
return `Le volume d'une pyramide est donné par la formule :
|
|
98
|
+
|
|
99
|
+
$$
|
|
100
|
+
V = \\frac{1}{3} \\times \\text{aire de la base} \\times \\text{hauteur}
|
|
101
|
+
$$
|
|
102
|
+
|
|
103
|
+
Ici, la base est un triangle rectangle dont une hauteur est $${ACSide}$ et sa base associée vaut $${ABSide}$. Son aire est donc égale à :
|
|
104
|
+
|
|
105
|
+
$$
|
|
106
|
+
${frac(multiply(ACSide, ABSide), 2).toTex()} = ${aera}
|
|
107
|
+
$$
|
|
108
|
+
|
|
109
|
+
Le volume de la pyramide est donc :
|
|
110
|
+
|
|
111
|
+
${alignTex([
|
|
112
|
+
["V", "=", `\\frac{1}{3}\\times ${aera} \\times ${h}`],
|
|
113
|
+
["", "=", getAnswer(identifiers)],
|
|
114
|
+
])}
|
|
115
|
+
`;
|
|
116
|
+
};
|
|
117
|
+
const getQuestionFromIdentifiers = (identifiers) => {
|
|
34
118
|
const question = {
|
|
35
|
-
answer:
|
|
36
|
-
instruction:
|
|
37
|
-
Calculer le volume de la pyramide en sachant que : $AB=${baseOfPyramidSides.ABSide}$, $AC=${baseOfPyramidSides.ACSide}$, $BC=${baseOfPyramidSides.BCSide}$ et $(AC)\\perp(AB)$.`,
|
|
119
|
+
answer: getAnswer(identifiers),
|
|
120
|
+
instruction: getInstruction(identifiers),
|
|
38
121
|
keys: [],
|
|
39
122
|
answerFormat: "tex",
|
|
40
|
-
ggbOptions:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
123
|
+
ggbOptions: getGGBOptions(identifiers),
|
|
124
|
+
identifiers,
|
|
125
|
+
hint: getHint(identifiers),
|
|
126
|
+
correction: getCorrection(identifiers),
|
|
44
127
|
};
|
|
45
128
|
return question;
|
|
46
129
|
};
|
|
@@ -76,52 +159,13 @@ const generatePropositions = (baseOfPyramidSides, h) => {
|
|
|
76
159
|
.toTex();
|
|
77
160
|
return [firstProposition, secondProposition];
|
|
78
161
|
};
|
|
79
|
-
const generateExercise = () => {
|
|
80
|
-
const h = randint(1, 11);
|
|
81
|
-
const base = generatePolygonWithGgbCmnds();
|
|
82
|
-
const commands = base.commands.concat([
|
|
83
|
-
`H=Point({${base.sideSizes.ABSide / 4},${base.sideSizes.ACSide / 4},${h}})`,
|
|
84
|
-
`SetFixed(H,true)`,
|
|
85
|
-
`ShowLabel(H,true)`,
|
|
86
|
-
`Pyra=Pyramid(Poly,H)`,
|
|
87
|
-
]);
|
|
88
|
-
return {
|
|
89
|
-
commands,
|
|
90
|
-
h,
|
|
91
|
-
baseOfPyramidSides: base.sideSizes,
|
|
92
|
-
};
|
|
93
|
-
};
|
|
94
162
|
const calculateVolume = (sideSize, h) => {
|
|
95
163
|
return new FractionNode(new MultiplyNode(new FractionNode((sideSize.ABSide * sideSize.ACSide).toTree(), (2).toTree()), h.toTree()), (3).toTree());
|
|
96
164
|
};
|
|
97
|
-
const generatePolygonWithGgbCmnds = () => {
|
|
98
|
-
const values = random(pythagoreTriplet);
|
|
99
|
-
const ABSide = values[0];
|
|
100
|
-
const ACSide = values[1];
|
|
101
|
-
return {
|
|
102
|
-
commands: [
|
|
103
|
-
`A=Point({0,0,0})`,
|
|
104
|
-
`B=Point({${ABSide},0,0})`,
|
|
105
|
-
`C=Point({0,${ACSide},0})`,
|
|
106
|
-
`ang=Angle(C,A,B)`,
|
|
107
|
-
`ShowLabel(ang,false)`,
|
|
108
|
-
`ShowLabel(A,True)`,
|
|
109
|
-
`ShowLabel(B,True)`,
|
|
110
|
-
`ShowLabel(C,True)`,
|
|
111
|
-
`SetFixed(A,true)`,
|
|
112
|
-
`SetFixed(B,true)`,
|
|
113
|
-
`SetFixed(C,true)`,
|
|
114
|
-
`Poly=Polygon(A,B,C)`,
|
|
115
|
-
],
|
|
116
|
-
sideSizes: { ABSide, ACSide, BCSide: values[2] },
|
|
117
|
-
};
|
|
118
|
-
};
|
|
119
165
|
export const volumeOfPyramid = {
|
|
120
166
|
id: "volumeOfPyramidWithTriangleRectBase",
|
|
121
167
|
label: "Calculer le volume d'une pyramide dont la base est un triangle rectangle",
|
|
122
|
-
levels: ["2nde"],
|
|
123
168
|
isSingleStep: true,
|
|
124
|
-
sections: ["Géométrie euclidienne"],
|
|
125
169
|
generator: (nb) => getDistinctQuestions(getVolumeOfPyramidWithTriangleRectBase, nb),
|
|
126
170
|
qcmTimer: 60,
|
|
127
171
|
freeTimer: 60,
|
|
@@ -129,4 +173,6 @@ export const volumeOfPyramid = {
|
|
|
129
173
|
isAnswerValid,
|
|
130
174
|
hasGeogebra: true,
|
|
131
175
|
subject: "Mathématiques",
|
|
176
|
+
hasHintAndCorrection: true,
|
|
177
|
+
getQuestionFromIdentifiers,
|
|
132
178
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geometricFirstTermsGeneralSum.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/sequences/geometric/geometricFirstTermsGeneralSum.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,
|
|
1
|
+
{"version":3,"file":"geometricFirstTermsGeneralSum.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/sequences/geometric/geometricFirstTermsGeneralSum.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAeT,MAAM,6BAA6B,CAAC;AAKrC,KAAK,WAAW,GAAG;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAsEF,eAAO,MAAM,6BAA6B,EAAE,QAAQ,CAAC,WAAW,CAc/D,CAAC"}
|