math-exercises 3.0.161 → 3.0.163
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/calculLitteral/distributivity/doubleDistributivityAdd.js +1 -1
- package/lib/exercises/math/calculLitteral/distributivity/doubleDistributivitySubstract.js +1 -1
- package/lib/exercises/math/functions/basics/inverseImageFunctionGeogebra.d.ts.map +1 -1
- package/lib/exercises/math/functions/basics/inverseImageFunctionGeogebra.js +172 -19
- package/lib/exercises/math/functions/cube/isPointOnCubicFunction.d.ts.map +1 -1
- package/lib/exercises/math/functions/cube/isPointOnCubicFunction.js +7 -1
- package/lib/math/geometry/point.d.ts +1 -0
- package/lib/math/geometry/point.d.ts.map +1 -1
- package/lib/math/geometry/point.js +3 -0
- package/lib/math/polynomials/generalAffine.d.ts +3 -0
- package/lib/math/polynomials/generalAffine.d.ts.map +1 -1
- package/lib/math/polynomials/generalAffine.js +12 -2
- package/lib/math/polynomials/trinom.d.ts +1 -0
- package/lib/math/polynomials/trinom.d.ts.map +1 -1
- package/lib/math/polynomials/trinom.js +13 -0
- package/lib/server.js +21 -0
- package/package.json +1 -1
|
@@ -72,7 +72,7 @@ $$
|
|
|
72
72
|
`;
|
|
73
73
|
};
|
|
74
74
|
const getHint = () => {
|
|
75
|
-
return "Développe et
|
|
75
|
+
return "Développe et réduis chacun des produits d'abord. Puis, additionne les deux résultats.";
|
|
76
76
|
};
|
|
77
77
|
const getCorrection = (identifiers) => {
|
|
78
78
|
const { affine1, affine2, affine3, type, affine4 } = identifiers;
|
|
@@ -72,7 +72,7 @@ $$
|
|
|
72
72
|
`;
|
|
73
73
|
};
|
|
74
74
|
const getHint = () => {
|
|
75
|
-
return "Développe et
|
|
75
|
+
return "Développe et réduis chacun des produits d'abord. Puis, soustrais les deux résultats.";
|
|
76
76
|
};
|
|
77
77
|
const getCorrection = (identifiers) => {
|
|
78
78
|
const { affine1, affine2, affine3, type, affine4 } = identifiers;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inverseImageFunctionGeogebra.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/basics/inverseImageFunctionGeogebra.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAiBT,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"inverseImageFunctionGeogebra.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/basics/inverseImageFunctionGeogebra.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAiBT,MAAM,6BAA6B,CAAC;AAgBrC,KAAK,WAAW,GAAG;IAEjB,MAAM,EAAE,MAAM,CAAC;IAIf,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;CACpB,CAAC;AA8bF,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,WAAW,CAoB9D,CAAC"}
|
|
@@ -3,7 +3,9 @@ import { getDistinctQuestions } from "../../../../exercises/utils/getDistinctQue
|
|
|
3
3
|
import { GeogebraConstructor } from "../../../../geogebra/geogebraConstructor.js";
|
|
4
4
|
import { Line } from "../../../../math/geometry/line.js";
|
|
5
5
|
import { Parabola } from "../../../../math/geometry/parabola.js";
|
|
6
|
-
import { Point } from "../../../../math/geometry/point.js";
|
|
6
|
+
import { Point, PointConstructor } from "../../../../math/geometry/point.js";
|
|
7
|
+
import { GeneralAffineConstructor } from "../../../../math/polynomials/generalAffine.js";
|
|
8
|
+
import { TrinomConstructor } from "../../../../math/polynomials/trinom.js";
|
|
7
9
|
import { randfloat } from "../../../../math/utils/random/randfloat.js";
|
|
8
10
|
import { randint } from "../../../../math/utils/random/randint.js";
|
|
9
11
|
import { round } from "../../../../math/utils/round.js";
|
|
@@ -44,7 +46,15 @@ const getGGBOptions = (identifiers) => {
|
|
|
44
46
|
const xMax = Math.max(...Xs);
|
|
45
47
|
const yMin = Math.min(...Ys);
|
|
46
48
|
const yMax = Math.max(...Ys);
|
|
47
|
-
const ggb = new GeogebraConstructor({
|
|
49
|
+
const ggb = new GeogebraConstructor({
|
|
50
|
+
commands,
|
|
51
|
+
xAxis: {
|
|
52
|
+
steps: 1,
|
|
53
|
+
},
|
|
54
|
+
yAxis: {
|
|
55
|
+
steps: 1,
|
|
56
|
+
},
|
|
57
|
+
});
|
|
48
58
|
return ggb.getOptions({
|
|
49
59
|
coords: ggb.getAdaptedCoords({
|
|
50
60
|
xMin,
|
|
@@ -209,26 +219,50 @@ const isAnswerValid = (ans, { answer, points, yValue }) => {
|
|
|
209
219
|
}
|
|
210
220
|
return true;
|
|
211
221
|
};
|
|
212
|
-
const getFeedback = (ans, { answer
|
|
213
|
-
const { points } = identifiers;
|
|
214
|
-
|
|
215
|
-
//A3-2. Intersection axe abscisse
|
|
216
|
-
//A3-3. Intersection ordonnée
|
|
217
|
-
//A3-4. Abscisse maximum
|
|
218
|
-
//A3-5. Abscisse minimum
|
|
219
|
-
//C3-1. Une seule solution au lieu de deux
|
|
220
|
-
//D. Lecture graphique peu précise (réponse proche mais pas correcte)
|
|
221
|
-
if (points.length === 1) {
|
|
222
|
+
const getFeedback = (ans, { answer, ...identifiers }) => {
|
|
223
|
+
const { points, yValue } = identifiers;
|
|
224
|
+
if (points.length === 2) {
|
|
222
225
|
const studentAns = valueParser(ans);
|
|
223
226
|
if (studentAns === false)
|
|
224
227
|
return {
|
|
225
228
|
errorType: "X",
|
|
226
229
|
feedback: "Réponse mal écrite",
|
|
227
230
|
};
|
|
228
|
-
|
|
231
|
+
const pointA = new Point("A", points[0][0], points[0][1]);
|
|
232
|
+
const pointB = new Point("B", points[1][0], points[1][1]);
|
|
233
|
+
const affine = GeneralAffineConstructor.fromPoints(pointA, pointB);
|
|
234
|
+
const image = affine.image(yValue);
|
|
235
|
+
if (Math.abs(studentAns - image.evaluate()) < 0.3) {
|
|
229
236
|
return {
|
|
230
237
|
errorType: "A3-1",
|
|
231
|
-
feedback:
|
|
238
|
+
feedback: `Pour lire une image, la technique est la suivante (ici l'image de $4$ est $2$) :
|
|
239
|
+
|
|
240
|
+

|
|
241
|
+
|
|
242
|
+
Et pour lire un antécédent, comment fait-on ? Sur quel axe, lit-on les antécédents ?`,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
if (affine.a.evaluate() !== 0) {
|
|
246
|
+
const root = affine.getRoot();
|
|
247
|
+
if (Math.abs(studentAns - root.evaluate()) < 0.3) {
|
|
248
|
+
return {
|
|
249
|
+
errorType: "A3-2",
|
|
250
|
+
feedback: "Tu as trouvé l'intersection de la courbe avec l'axe des abscisses. Cette technique est pertinente pour trouver les antécédents de 0, mais pas pour trouver les antécédents d'un nombre différent de 0. De manière générale, comment fait-on pour lire les antécédents d'un nombre ?",
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
const ordOrigine = affine.b.evaluate();
|
|
255
|
+
if (Math.abs(studentAns - ordOrigine) < 0.3) {
|
|
256
|
+
return {
|
|
257
|
+
errorType: "A3-3",
|
|
258
|
+
feedback: "Tu as trouvé l'intersection de la courbe avec l'axe des ordonnés, mais cela n'a a priori pas de rapports avec la recherche d'antécédent. Comment fait-on pour lire un antécédent ?",
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
const ansNb = answer.unfrenchify();
|
|
262
|
+
if (Math.abs(studentAns - ansNb) < 1) {
|
|
263
|
+
return {
|
|
264
|
+
errorType: "D",
|
|
265
|
+
feedback: "Ta lecture sur le graphique n'est pas assez précise, mais tu as bien compris la procédure à suivre pour répondre à la question.",
|
|
232
266
|
};
|
|
233
267
|
}
|
|
234
268
|
return {
|
|
@@ -237,17 +271,136 @@ const getFeedback = (ans, { answer: _answer, ...identifiers }) => {
|
|
|
237
271
|
};
|
|
238
272
|
}
|
|
239
273
|
else {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
274
|
+
const trinom = TrinomConstructor.fromPoints(points.map((p) => PointConstructor.fromCoords(p)));
|
|
275
|
+
const studentAns = ans.split("\\text{ et }");
|
|
276
|
+
if (studentAns.length === 1) {
|
|
277
|
+
const v = valueParser(studentAns[0]);
|
|
278
|
+
if (v === false)
|
|
279
|
+
return { errorType: "X", feedback: "Réponse mal écrite" };
|
|
280
|
+
const validPoints = points.filter((p) => p[1] === yValue);
|
|
281
|
+
if (validPoints.length === 2 &&
|
|
282
|
+
validPoints.some((p) => Math.abs(p[0] - v) < 0.2)) {
|
|
283
|
+
return {
|
|
284
|
+
errorType: "C3-1",
|
|
285
|
+
feedback: "Tu as trouvé une partie de la réponse, mais ce n'est pas complet. Combien un nombre peut-il avoir d'antécédent ?",
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
const values = studentAns.map((e) => valueParser(e));
|
|
290
|
+
const extrema = round(trinom.getBeta(), 5);
|
|
291
|
+
const image = round(trinom.calculate(yValue), 5);
|
|
292
|
+
const roots = trinom.getRoots();
|
|
293
|
+
const c = trinom.c;
|
|
294
|
+
const checkValue = (v) => {
|
|
295
|
+
if (Math.abs(v - image) < 0.2) {
|
|
296
|
+
return {
|
|
297
|
+
errorType: "A3-1",
|
|
298
|
+
feedback: `Pour lire une image, la technique est la suivante (ici l'image de $4$ est $2$) :
|
|
299
|
+
|
|
300
|
+

|
|
301
|
+
|
|
302
|
+
Et pour lire un antécédent, comment fait-on ? Sur quel axe, lit-on les antécédents ?`,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
if (Math.abs(v - c) < 0.2)
|
|
306
|
+
return {
|
|
307
|
+
errorType: "A3-3",
|
|
308
|
+
feedback: "Tu as trouvé l'intersection de la courbe avec l'axe des ordonnés, mais cela n'a a priori pas de rapports avec la recherche d'antécédent. Comment fait-on pour lire un antécédent ?",
|
|
309
|
+
};
|
|
310
|
+
if (Math.abs(v - extrema) < 0.2)
|
|
311
|
+
if (trinom.a < 0)
|
|
312
|
+
return {
|
|
313
|
+
errorType: "A3-4",
|
|
314
|
+
feedback: "Tu as trouvé le maximum de la courbe, mais cela n'a a priori pas de rapports avec la recherche d'antécédent. Comment fait-on pour lire un antécédent ?",
|
|
315
|
+
};
|
|
316
|
+
else {
|
|
317
|
+
return {
|
|
318
|
+
errorType: "A3-5",
|
|
319
|
+
feedback: "Tu as trouvé le minimum de la courbe, mais cela n'a a priori pas de rapports avec la recherche d'antécédent. Comment fait-on pour lire un antécédent ?",
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
if (roots.length) {
|
|
323
|
+
if (Math.abs(v - roots[0]) < 0.2 || Math.abs(v - roots[1]) < 0.2) {
|
|
324
|
+
return {
|
|
325
|
+
errorType: "A3-2",
|
|
326
|
+
feedback: "Tu as trouvé l'intersection de la courbe avec l'axe des abscisses. Cette technique est pertinente pour trouver les antécédents de 0, mais pas pour trouver les antécédents d'un nombre différent de 0. De manière générale, comment fait-on pour lire les antécédents d'un nombre ?",
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
errorType: "X",
|
|
332
|
+
feedback: "Non corrélable",
|
|
333
|
+
};
|
|
243
334
|
};
|
|
335
|
+
const types = values.map((v) => checkValue(v));
|
|
336
|
+
if (values.length === 1)
|
|
337
|
+
return types[0];
|
|
338
|
+
if (types[0].errorType === types[1].errorType) {
|
|
339
|
+
return types[0];
|
|
340
|
+
}
|
|
341
|
+
if (types[0].errorType === "X" && types[1].errorType !== "X") {
|
|
342
|
+
return types[1];
|
|
343
|
+
}
|
|
344
|
+
else
|
|
345
|
+
return types[0];
|
|
244
346
|
}
|
|
245
347
|
};
|
|
246
348
|
const getMethodology = () => {
|
|
349
|
+
// const commands = [
|
|
350
|
+
// "f(x) = (x+2)(x-1)",
|
|
351
|
+
// `Conique_1 : 1.76x^2+6.43y^2+0.77x-51.42y = -102.21`,
|
|
352
|
+
// `step = Slider(1, 4, 1, 1, 100, false, true, true, false)`,
|
|
353
|
+
// "C = (2,4)",
|
|
354
|
+
// `SetVisibleInView(step, 1, false)`,
|
|
355
|
+
// `ShowLabel(C, false)`,
|
|
356
|
+
// "SetFixed(C, true, false)",
|
|
357
|
+
// `SetConditionToShowObject(C, step>1)`,
|
|
358
|
+
// "D = (-3,4)",
|
|
359
|
+
// `ShowLabel(D, false)`,
|
|
360
|
+
// "SetFixed(D, true, false)",
|
|
361
|
+
// `SetConditionToShowObject(D, step>1)`,
|
|
362
|
+
// `g: y=4`,
|
|
363
|
+
// `SetConditionToShowObject(g, step>1)`,
|
|
364
|
+
// "A = (-3,0)",
|
|
365
|
+
// `ShowLabel(A, false)`,
|
|
366
|
+
// "SetFixed(A, true, false)",
|
|
367
|
+
// `SetConditionToShowObject(A, step>2)`,
|
|
368
|
+
// "B = (2,0)",
|
|
369
|
+
// `ShowLabel(B, false)`,
|
|
370
|
+
// "SetFixed(B, true, false)",
|
|
371
|
+
// `SetConditionToShowObject(B, step>2)`,
|
|
372
|
+
// "S_1 = Segment(B,C)",
|
|
373
|
+
// `SetConditionToShowObject(B, step>2)`,
|
|
374
|
+
// `SetLineStyle(S_1, 2)`,
|
|
375
|
+
// "S_2 = Segment(A,D)",
|
|
376
|
+
// `SetConditionToShowObject(B, step>2)`,
|
|
377
|
+
// `SetLineStyle(S_2, 2)`,
|
|
378
|
+
// `text1 = Text("$\\scriptsize 2\\text{ est un}\\\\ \\text{antécédent de }4\\\\ \\text{ par la fonction }f$", (2.69357, 1.61646))`,
|
|
379
|
+
// `SetConditionToShowObject(text1, step>2)`,
|
|
380
|
+
// `SetConditionToShowObject(text1, step>2)`,
|
|
381
|
+
// `I = (2.64071, 0.39819)`,
|
|
382
|
+
// `SetVisibleInView(I, 1, false)`,
|
|
383
|
+
// `v = Vector(I, B)`,
|
|
384
|
+
// `SetConditionToShowObject(v, step>2)`,
|
|
385
|
+
// `text2 = Text("$\\scriptsize -3 \\text{ est un autre} \\\\ \\text{antécédent de } 4 \\\\ \\text{par la fonction }f$", (-6.27307, 1.61256))`,
|
|
386
|
+
// `SetConditionToShowObject(text2, step>3)`,
|
|
387
|
+
// `H = (-3.83865, 0.62044)`,
|
|
388
|
+
// `SetVisibleInView(H, 1, false)`,
|
|
389
|
+
// `u = Vector(H, A)`,
|
|
390
|
+
// `SetConditionToShowObject(u, step>3)`,
|
|
391
|
+
// `StartAnimation(step, true)`,
|
|
392
|
+
// ];
|
|
247
393
|
return {
|
|
248
|
-
methodology: `
|
|
394
|
+
methodology: `Chercher des antécédents d'un réel $4$ par la fonction f, c'est déterminer les réels $x$ tels que $f(x)=4$.
|
|
395
|
+
|
|
396
|
+
La donnée $4$ se trouve donc sur l'axe des ordonnées et les antécédents cherchés doivent donc se trouver sur l'axe des abscisses !
|
|
397
|
+
|
|
398
|
+
Voici la technique à employer pour trouver les antécédents de $4$ :
|
|
249
399
|
|
|
250
|
-
`,
|
|
401
|
+
// methodologyGGBOptions: ggb.getOptions({
|
|
402
|
+
// coords: [-8, 6, -3, 5],
|
|
403
|
+
// }),
|
|
251
404
|
};
|
|
252
405
|
};
|
|
253
406
|
export const inverseImageFunctionGeogebra = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"isPointOnCubicFunction.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/cube/isPointOnCubicFunction.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAaT,MAAM,6BAA6B,CAAC;AAKrC,OAAO,EACL,eAAe,EAEhB,MAAM,qCAAqC,CAAC;AAK7C,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,eAAe,CAAC;IACnB,CAAC,EAAE,eAAe,CAAC;CACpB,CAAC;
|
|
1
|
+
{"version":3,"file":"isPointOnCubicFunction.d.ts","sourceRoot":"","sources":["../../../../../src/exercises/math/functions/cube/isPointOnCubicFunction.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAaT,MAAM,6BAA6B,CAAC;AAKrC,OAAO,EACL,eAAe,EAEhB,MAAM,qCAAqC,CAAC;AAK7C,KAAK,WAAW,GAAG;IACjB,CAAC,EAAE,eAAe,CAAC;IACnB,CAAC,EAAE,eAAe,CAAC;CACpB,CAAC;AAgGF,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,WAAW,CAiBxD,CAAC"}
|
|
@@ -34,7 +34,13 @@ const getInstruction = (identifiers) => {
|
|
|
34
34
|
return `Le point $${point.toTexWithCoords()}$ appartient-il à la courbe de la fonction cube ?`;
|
|
35
35
|
};
|
|
36
36
|
const getHint = () => {
|
|
37
|
-
return `Un point de coordonnées $(x;y)$ appartient à la courbe d'une fonction $f$ si et seulement $y = f(x)
|
|
37
|
+
return `Un point de coordonnées $(x;y)$ appartient à la courbe d'une fonction $f$ si et seulement $y = f(x)$.
|
|
38
|
+
|
|
39
|
+
On rappelle de plus que la fonction cube est la fonction $f$ définie sur $\\mathbb{R}$ par :
|
|
40
|
+
|
|
41
|
+
$$
|
|
42
|
+
f(x) = x^3
|
|
43
|
+
$$`;
|
|
38
44
|
};
|
|
39
45
|
const getCorrection = (identifiers) => {
|
|
40
46
|
const { x, y } = identifiers;
|
|
@@ -15,6 +15,7 @@ export declare abstract class PointConstructor {
|
|
|
15
15
|
static origin(name?: string): Point;
|
|
16
16
|
static random(name: string, min?: number, max?: number): Point;
|
|
17
17
|
static fromIdentifiers(identifiers: PointIdentifiers): Point;
|
|
18
|
+
static fromCoords(coords: number[], name?: string): Point;
|
|
18
19
|
static onSegment(segment: Segment, name: string, { spacing, coefficient, }?: {
|
|
19
20
|
spacing?: number;
|
|
20
21
|
coefficient?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../../src/math/geometry/point.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,aAAa,EACb,eAAe,EAChB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sDAAsD,CAAC;AAC1F,OAAO,EAEL,eAAe,EAChB,MAAM,qCAAqC,CAAC;AAM7C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAQvC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,eAAe,CAAC;IACnB,CAAC,EAAE,eAAe,CAAC;CACpB,CAAC;AACF,8BAAsB,gBAAgB;IACpC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE;IAGrC,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM;IAKhC,MAAM,CAAC,MAAM,CAAC,IAAI,SAAM;IAGxB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAM,EAAE,GAAG,SAAK,GAAG,KAAK;IAMvD,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,gBAAgB;
|
|
1
|
+
{"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../../src/math/geometry/point.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,aAAa,EACb,eAAe,EAChB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sDAAsD,CAAC;AAC1F,OAAO,EAEL,eAAe,EAChB,MAAM,qCAAqC,CAAC;AAM7C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAQvC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,eAAe,CAAC;IACnB,CAAC,EAAE,eAAe,CAAC;CACpB,CAAC;AACF,8BAAsB,gBAAgB;IACpC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE;IAGrC,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM;IAKhC,MAAM,CAAC,MAAM,CAAC,IAAI,SAAM;IAGxB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAM,EAAE,GAAG,SAAK,GAAG,KAAK;IAMvD,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,gBAAgB;IAOpD,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,SAAM;IAO9C,MAAM,CAAC,SAAS,CACd,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,EACZ,EACE,OAAa,EACb,WAAW,GACZ,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO;IAQpD,MAAM,CAAC,eAAe,CACpB,KAAK,EAAE,MAAM,EACb,EACE,KAAK,EACL,WAAW,EACX,mBAAmB,GACpB,EAAE;QACD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC9B;IA+BH,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM;IAejC,MAAM,CAAC,uBAAuB,CAC5B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,KAAK,EAClB,MAAM,EAAE,aAAa,GAAG,MAAM,EAC9B,KAAK,EAAE,aAAa,GAAG,MAAM,EAC7B,OAAO,GAAE;QACP,gBAAgB,EAAE,OAAO,CAAC;QAC1B,gBAAgB,EAAE,OAAO,CAAC;QAC1B,UAAU,EAAE,OAAO,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC;KAMlB;CAwBJ;AAED,qBAAa,KAAK;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,aAAa,CAAC;IACjB,CAAC,EAAE,aAAa,CAAC;gBAEf,IAAI,EAAE,MAAM,EACZ,CAAC,EAAE,aAAa,GAAG,MAAM,EACzB,CAAC,EAAE,aAAa,GAAG,MAAM;IAO3B,KAAK,IAAI,MAAM;IAGf,aAAa,IAAI,gBAAgB;IAQjC,eAAe,IAAI,MAAM;IAGzB,QAAQ,IAAI,MAAM;IAIlB,UAAU,IAAI,MAAM;IAIpB,UAAU,IAAI,MAAM;IAIpB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,SAAM,GAAG,KAAK;IAOzC,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,SAAM,GAAG,KAAK;IAQrC,UAAU,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM;IAK5B,cAAc,CAAC,CAAC,EAAE,KAAK,GAAG,aAAa;IAMvC,MAAM,CAAC,CAAC,EAAE,KAAK,GAAG,OAAO;IAGzB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK;IAK5B,YAAY;IAGZ,YAAY,CAAC,EACX,OAAc,EACd,gBAAwB,EACxB,SAAgB,EAChB,KAAK,EACL,IAAI,EACJ,KAAK,EACL,KAAK,GACN,GAAE,kBAAuB;IAsB1B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK;IAiBpC,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,MAAM;IAkBhE,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,SAAkB;IAIrD,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,SAAkB;IAI1C,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,SAAkB;IAKhD,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe;IAG/B,SAAS,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,EAAE,CAAC,EAAE,aAAa,GAAG,MAAM;CAO/D"}
|
|
@@ -35,6 +35,9 @@ export class PointConstructor {
|
|
|
35
35
|
static fromIdentifiers(identifiers) {
|
|
36
36
|
return new Point(identifiers.name, NodeConstructor.fromIdentifiers(identifiers.x), NodeConstructor.fromIdentifiers(identifiers.y));
|
|
37
37
|
}
|
|
38
|
+
static fromCoords(coords, name = "A") {
|
|
39
|
+
return new Point(name, new NumberNode(coords[0]), new NumberNode(coords[1]));
|
|
40
|
+
}
|
|
38
41
|
static onSegment(segment, name, { spacing = 0.1, coefficient, } = {}) {
|
|
39
42
|
const coeff = coefficient ?? randfloat(spacing, 1 - spacing);
|
|
40
43
|
const vector = VectorConstructor.fromSegment(segment).times(coeff.toTree());
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { AlgebraicNode } from "../../tree/nodes/algebraicNode.js";
|
|
2
2
|
import { NodeIdentifiers } from "../../tree/nodes/nodeConstructor.js";
|
|
3
3
|
import { IntervalNode } from "../../tree/nodes/sets/intervalNode.js";
|
|
4
|
+
import { Point } from "../geometry/point.js";
|
|
4
5
|
export declare abstract class GeneralAffineConstructor {
|
|
5
6
|
static fromIdentifiers(identifiers: GeneralAffineIdentifiers): GeneralAffine;
|
|
6
7
|
static randomInts({ allowBNull }: {
|
|
7
8
|
allowBNull?: boolean | undefined;
|
|
8
9
|
}, variable?: string): GeneralAffine;
|
|
10
|
+
static fromPoints(pointA: Point, pointB: Point): GeneralAffine;
|
|
9
11
|
}
|
|
10
12
|
export type GeneralAffineIdentifiers = {
|
|
11
13
|
id: "affine";
|
|
@@ -25,5 +27,6 @@ export declare class GeneralAffine {
|
|
|
25
27
|
toTree(): import("../../tree/nodes/operators/addNode.js").AddNode | import("../../tree/nodes/operators/multiplyNode.js").MultiplyNode;
|
|
26
28
|
xIntersect(aff: GeneralAffine): AlgebraicNode | undefined;
|
|
27
29
|
opposite(): GeneralAffine;
|
|
30
|
+
image(x: AlgebraicNode | number): AlgebraicNode;
|
|
28
31
|
}
|
|
29
32
|
//# sourceMappingURL=generalAffine.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generalAffine.d.ts","sourceRoot":"","sources":["../../../src/math/polynomials/generalAffine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAElE,OAAO,EACL,eAAe,EAEhB,MAAM,qCAAqC,CAAC;AAU7C,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"generalAffine.d.ts","sourceRoot":"","sources":["../../../src/math/polynomials/generalAffine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAElE,OAAO,EACL,eAAe,EAEhB,MAAM,qCAAqC,CAAC;AAU7C,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AACrE,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAG7C,8BAAsB,wBAAwB;IAC5C,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,wBAAwB;IAM5D,MAAM,CAAC,UAAU,CAAC,EAAE,UAAiB,EAAE;;KAAA,EAAE,QAAQ,SAAM;IAOvD,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK;CAU/C;AACD,MAAM,MAAM,wBAAwB,GAAG;IACrC,EAAE,EAAE,QAAQ,CAAC;IACb,CAAC,EAAE,eAAe,CAAC;IACnB,CAAC,EAAE,eAAe,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,qBAAa,aAAa;IACxB,CAAC,EAAE,aAAa,CAAC;IACjB,CAAC,EAAE,aAAa,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;gBAGf,CAAC,EAAE,MAAM,GAAG,aAAa,EACzB,CAAC,EAAE,MAAM,GAAG,aAAa,EACzB,QAAQ,GAAE,MAAY;IAUxB,aAAa,IAAI,wBAAwB;IAQzC,OAAO,IAAI,aAAa;IAKxB,mBAAmB,IAAI,YAAY;IAQnC,mBAAmB,IAAI,YAAY;IASnC,MAAM;IAMN,UAAU,CAAC,GAAG,EAAE,aAAa;IAI7B,QAAQ;IAMR,KAAK,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM;CAGhC"}
|
|
@@ -15,6 +15,13 @@ export class GeneralAffineConstructor {
|
|
|
15
15
|
static randomInts({ allowBNull = true }, variable = "x") {
|
|
16
16
|
return new GeneralAffine(randint(-10, 11, [0]), randint(-10, 11, allowBNull ? [] : [0]), variable);
|
|
17
17
|
}
|
|
18
|
+
static fromPoints(pointA, pointB) {
|
|
19
|
+
if (pointA.x.equals(pointB.x))
|
|
20
|
+
throw new Error("Not an affine function");
|
|
21
|
+
const a = frac(substract(pointB.y, pointA.y), substract(pointB.x, pointA.x)).simplify();
|
|
22
|
+
const b = substract(pointA.y, multiply(a, pointA.x)).simplify();
|
|
23
|
+
return new GeneralAffine(a, b);
|
|
24
|
+
}
|
|
18
25
|
}
|
|
19
26
|
export class GeneralAffine {
|
|
20
27
|
a;
|
|
@@ -25,8 +32,6 @@ export class GeneralAffine {
|
|
|
25
32
|
this.a = a.toTree();
|
|
26
33
|
else
|
|
27
34
|
this.a = a;
|
|
28
|
-
if (this.a.evaluate() === 0)
|
|
29
|
-
throw new Error("Forbidden division by zero");
|
|
30
35
|
if (typeof b === "number")
|
|
31
36
|
this.b = b.toTree();
|
|
32
37
|
else
|
|
@@ -42,6 +47,8 @@ export class GeneralAffine {
|
|
|
42
47
|
};
|
|
43
48
|
}
|
|
44
49
|
getRoot() {
|
|
50
|
+
if (this.a.evaluate() === 0)
|
|
51
|
+
throw new Error("No root for constant function");
|
|
45
52
|
return frac(opposite(this.b), this.a).simplify();
|
|
46
53
|
}
|
|
47
54
|
getPositiveInterval() {
|
|
@@ -76,4 +83,7 @@ export class GeneralAffine {
|
|
|
76
83
|
opposite() {
|
|
77
84
|
return new GeneralAffine(opposite(this.a).simplify(), opposite(this.b).simplify());
|
|
78
85
|
}
|
|
86
|
+
image(x) {
|
|
87
|
+
return add(multiply(this.a, x), this.b).simplify();
|
|
88
|
+
}
|
|
79
89
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trinom.d.ts","sourceRoot":"","sources":["../../../src/math/polynomials/trinom.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EAAO,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAErE,OAAO,EAEL,YAAY,EACb,MAAM,4CAA4C,CAAC;AAGpD,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAG7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAM7C,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"trinom.d.ts","sourceRoot":"","sources":["../../../src/math/polynomials/trinom.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ import { gcd } from "../utils/arithmetic/gcd.js";
|
|
|
14
14
|
import { randint } from "../utils/random/randint.js";
|
|
15
15
|
import { random } from "../../utils/alea/random.js";
|
|
16
16
|
import { blueMain } from "../../geogebra/colors.js";
|
|
17
|
+
import { round } from "../utils/round.js";
|
|
17
18
|
export class TrinomConstructor {
|
|
18
19
|
static random(aOpts, bOpts, cOpts) {
|
|
19
20
|
const a = randint(aOpts?.min ?? -9, aOpts?.max ?? 10, aOpts?.excludes ?? [0]);
|
|
@@ -86,6 +87,18 @@ export class TrinomConstructor {
|
|
|
86
87
|
const a = ySummit / ((x2 - x1) / 2) ** 2;
|
|
87
88
|
return this.fromRoots(roots, a);
|
|
88
89
|
}
|
|
90
|
+
static fromPoints(points) {
|
|
91
|
+
const sorted = [...points.sort((a, b) => a.x.evaluate() - b.x.evaluate())];
|
|
92
|
+
const [x1, y1] = [sorted[0].x.evaluate(), sorted[0].y.evaluate()];
|
|
93
|
+
const [x2, y2] = [sorted[1].x.evaluate(), sorted[1].y.evaluate()];
|
|
94
|
+
const [x3, y3] = [sorted[2].x.evaluate(), sorted[2].y.evaluate()];
|
|
95
|
+
const delta1 = round((y2 - y1) / (x2 - x1), 5);
|
|
96
|
+
const delta2 = round((y3 - y2) / (x3 - x2), 5);
|
|
97
|
+
const a = round((delta2 - delta1) / (x3 - x1), 5);
|
|
98
|
+
const b = round(delta1 - a * (x1 + x2), 5);
|
|
99
|
+
const c = round(y1 - a * x1 * x1 - b * x1, 5);
|
|
100
|
+
return new Trinom(a, b, c);
|
|
101
|
+
}
|
|
89
102
|
}
|
|
90
103
|
export class Trinom extends Polynomial {
|
|
91
104
|
a;
|
package/lib/server.js
CHANGED
|
@@ -226,6 +226,27 @@ const runServer = () => {
|
|
|
226
226
|
.id,
|
|
227
227
|
});
|
|
228
228
|
});
|
|
229
|
+
app.post("/feedback", jsonParser, (req, res) => {
|
|
230
|
+
const exoId = req.query.exoId;
|
|
231
|
+
const options = req.query.options
|
|
232
|
+
? JSON.parse(decodeURIComponent(req.query.options))
|
|
233
|
+
: undefined;
|
|
234
|
+
const { ans, feedbackProps } = req.body;
|
|
235
|
+
const exoIndex = allExercises.findIndex((exo) => exo.id == exoId);
|
|
236
|
+
const exo = allExercises[exoIndex];
|
|
237
|
+
if (!exo) {
|
|
238
|
+
res.send("Exo not found");
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (!exo.getFeedback) {
|
|
242
|
+
res.send("No Feedback implemented");
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
const result = exo.getFeedback(ans, feedbackProps, options) ?? false;
|
|
246
|
+
res.json({
|
|
247
|
+
result,
|
|
248
|
+
});
|
|
249
|
+
});
|
|
229
250
|
app.post("/vea", jsonParser, (req, res) => {
|
|
230
251
|
const exoId = req.query.exoId;
|
|
231
252
|
const options = req.query.options
|