diff --git a/src/exercices/2NDE/2MI1-7.ts b/src/exercices/2NDE/2MI1-7.ts new file mode 100644 index 0000000000000000000000000000000000000000..b226231aef9956455e41513285f677a3339fa57e --- /dev/null +++ b/src/exercices/2NDE/2MI1-7.ts @@ -0,0 +1,414 @@ +/** + * 2MI-7.ts + * @author Régis Ferreira Da Silva + * @author Thibault Giauffret + * @date 2024-12-19 + */ + +import { choice, combinaisonListes } from '../../lib/outils/arrayOutils' +import Exercice from '../Exercice' +import { chiffresSignificatifs } from '../../lib/outils_phys/ecritures' +import { listeQuestionsToContenu, randint } from '../../modules/outils.js' +import { ajouteChampTexteMathLive } from '../../lib/interactif/questionMathLive.js' +import { approximatelyCompare } from '../../lib/interactif/comparisonFunctions' +import { handleAnswers } from '../../lib/interactif/gestionInteractif' +import { prenom } from '../../lib/outils/Personne' +import { fixeBordures, mathalea2d } from '../../modules/2dGeneralites.js' +import { point, tracePoint } from '../../lib/2d/points' +import { repere } from '../../lib/2d/reperes' +import { type Segment, segment, vecteur } from '../../lib/2d/segmentsVecteurs' +import { labelPoint, latex2d } from '../../lib/2d/textes' +import { texNombre } from '../../lib/outils/texNombre' +import { miseEnEvidence } from '../../lib/outils/embellissements' + +// Configuration de l'exercice +export const titre = 'Approcher le vecteur vitesse d\'un point à l’aide du vecteur déplacement.' +export const interactifReady = true +export const interactifType = 'mathLive' +export const dateDePublication = '19/12/2024' +export const uuid = 'bd387' +export const refs = { + 'fr-fr': ['2MI1-7'] +} + +export default class vecteurvitesse extends Exercice { + constructor () { + super() + this.nbQuestions = 1 + this.sup = 1 + this.besoinFormulaireNumerique = ['Choix des questions', 2, '1 : Novice (1 dimension et uniforme)\n2 : Confirmé (1 dimension et accéléré)\n3 : Expert (2 dimensions)'] + } + + nouvelleVersion () { + this.listeQuestions = [] + this.listeCorrections = [] + + let typesDeQuestionsDisponibles + if (this.sup === 1) { + typesDeQuestionsDisponibles = ['novice'] + } else if (this.sup === 2) { + typesDeQuestionsDisponibles = ['confirme'] + } else if (this.sup === 3) { + typesDeQuestionsDisponibles = ['expert'] + } + + const listeTypeDeQuestions = combinaisonListes(typesDeQuestionsDisponibles, this.nbQuestions) + + for (let i = 0, cpt = 0, a, b, tau; i < this.nbQuestions && cpt < 50;) { + // ------------------------ + // Paramètres de la question + // ------------------------ + const vertical = choice([true, false]) // On choisit aléatoirement si le mouvement est vertical ou horizontal + const accelere = choice(['+', '-']) // On choisit aléatoirement si le mouvement est accéléré, ralenti ou uniforme + const duree = randint(5, 15) // Durée totale + a = randint(1, 3) / 3 + b = randint(1, 4) + const nbcs = 2 // Nombre de chiffres significatifs + + // ------------------------ + // Préparation du graphique + // ------------------------ + + // Configuration + const fixedWidth = 10 // On fixe le graphique à 10 cm de large + let maxValue = 1 + let nbPoints = randint(5, 10) + tau = duree / nbPoints + let ti = randint(0, nbPoints - 2) + let tipun = ti + 1 + let roundFactor1 = 2 + let roundFactor2 = 2 + + // Calcul des coordonnées des points (ici les valeurs sont données en cm) + let x = [] + let x_value = [] + let y = [] + const y_value = [] + + let dx = 0 + let deplacement = 0 + let vitesse = 0 + + let labelPos = 'above left' + if (this.sup === 1) { + dx = maxValue / nbPoints + deplacement = dx + vitesse = deplacement / tau + x = Array.from({ length: nbPoints }, (_, i) => i * dx * fixedWidth / maxValue) + x_value = Array.from({ length: nbPoints }, (_, i) => x[i] * maxValue / fixedWidth) + y = Array.from({ length: nbPoints }, () => 0) + labelPos = 'above' + } else if (this.sup === 2) { + maxValue = 10 + let valeurAccelere + const vitesseInitiale = 1.4 + if (accelere === '+') { + valeurAccelere = 0.1 + } else if (accelere === '-') { + valeurAccelere = -0.1 + } else { + valeurAccelere = 0 + } + + if (vertical) { + x = Array.from({ length: nbPoints }, () => 5) + y = Array.from({ length: nbPoints }, (_, i) => 0.5 * valeurAccelere * Math.pow(i * tau, 2) + vitesseInitiale * i * tau) + deplacement = y[tipun] - y[ti] + } else { + for (let i = 0; i < nbPoints; i++) { + const value = 0.5 * valeurAccelere * Math.pow(i * tau, 2) + vitesseInitiale * i * tau + console.log(value) + if (value <= maxValue) { + x.push(value) + y.push(b) + } + } + nbPoints = x.length + ti = randint(0, nbPoints - 2) + tipun = ti + 1 + deplacement = x[tipun] - x[ti] + } + vitesse = deplacement / tau + labelPos = 'above right' + } else { + maxValue = 10 + let valeurAccelere + const vitesseInitiale = 1.4 + if (accelere === '+') { + valeurAccelere = 0.1 + } else if (accelere === '-') { + valeurAccelere = -0.1 + } else { + valeurAccelere = 0 + } + const signe = choice([1, -1]) + if (signe === -1) { + labelPos = 'above' + } + for (let i = 0; i < nbPoints; i++) { + const value = 0.5 * valeurAccelere * Math.pow(i * tau, 2) + vitesseInitiale * i * tau + if (value <= maxValue) { + x.push(value) + y.push(signe * a * x[i] + b) + } + } + nbPoints = x.length + ti = randint(0, nbPoints - 2) + tipun = ti + 1 + deplacement = Math.sqrt(Math.pow(x[tipun] - x[ti], 2) + Math.pow(y[tipun] - y[ti], 2)) + vitesse = deplacement / tau + } + + // Création des points + const points = [] + const tracePoints = [] + const labelPoints = [] + for (let i = 0; i < nbPoints; i++) { + points.push(point(x[i], y[i], '$M_' + i + '$', labelPos)) + tracePoints.push(tracePoint(points[i], 'blue')) + labelPoints.push(labelPoint(points[i], 'blue')) + } + + // Création du vecteur déplacement + const vecteurDeplacement = segment(points[ti], points[tipun], 'red') + vecteurDeplacement.styleExtremites = '->' + vecteurDeplacement.epaisseur = 1.5 + + // Limites du graphique + const xmin = 0 + const xmax = maxValue + let ymin + if (Math.min(...y) > 0) { + ymin = 0 + } else { + ymin = Math.min(...y) - 1 + } + const ymax = Math.max(...y) + 1 + + let reponse0, reponse1, reponse2 + + // ------------------------ + // Création de la question selon le niveau + // ------------------------ + switch (listeTypeDeQuestions[i]) { + case 'novice': + this.question = `Lors d'une séance de TP, ${prenom()} observe le déplacement d'un palet sur une table horizontale. Le centre de ce palet est repéré par une croix. <br> + Entre chaque position du palet, il se passe ${chiffresSignificatifs(tau, nbcs)} seconde(s). <br>` + // On énonce la question + + this.question += this.creerGraphique1D({ Xmin: xmin, Xmax: xmax, xMajorTickDistance: 1, subdivision: 10, fixedWidth }, { tracePoints, labelPoints }) + + this.question += `$${miseEnEvidence('a)')}$ Indiquer à quel point se placer pour déterminer la norme du vecteur vitesse $\\overrightarrow{v_{${ti}}}$.<br>` + + // On y ajoute le champ de réponse + reponse0 = ti + this.question += ajouteChampTexteMathLive(this, 3 * i, 'inline largeur01', { texteAvant: 'Se placer au point : $M_{\\cdots}$' }) + handleAnswers(this, 3 * i, { reponse: { value: reponse0, compare: approximatelyCompare, tolerance: 1 } })// tolerance de 1 + + // On écrit la correction + this.correction = `$${miseEnEvidence('a)')}$ Il est nécessaire de se placer au point $M_{${ti}}$.<br>` + + this.question += `<br>$${miseEnEvidence('b)')}$ Déterminer la norme du vecteur déplacement $\\overrightarrow{M_{${ti}}M_{${tipun}}}$.<br>` + + if (x_value[tipun] >= 1) { + roundFactor2 = 3 + } + if (x_value[ti] >= 1) { + roundFactor1 = 3 + } + + // On génère la réponse + reponse1 = Math.round(x_value[tipun] * Math.pow(10, roundFactor2)) / Math.pow(10, roundFactor2) - Math.round(x_value[ti] * Math.pow(10, roundFactor1)) / Math.pow(10, roundFactor1) + this.question += ajouteChampTexteMathLive(this, 3 * i + 1, 'inline largeur01', { texteAvant: `Norme du vecteur déplacement $\\overrightarrow{M_{${ti}}M_{${tipun}}}$ = `, texteApres: 'm' }) + handleAnswers(this, 3 * i + 1, { reponse: { value: reponse1, compare: approximatelyCompare } }) // tolerance de 0.1 + + // On écrit la correction + this.correction += `$${miseEnEvidence('b)')}$ Dans un premier temps, on trace le vecteur déplacement $\\overrightarrow{M_{${ti}}M_{${tipun}}}$ : <br><br>` + + // Ajout du vecteur déplacement + tracePoints.push(vecteurDeplacement) + this.correction += this.creerGraphique1D({ Xmin: xmin, Xmax: xmax, xMajorTickDistance: 1, subdivision: 10, fixedWidth }, { tracePoints, labelPoints }) + + this.correction += `Ensuite, il s'agit de déterminer graphiquement la norme de ce vecteur déplacement $||\\overrightarrow{M_{${ti}}M_{${tipun}}}||$. Ici, on lit : $||\\overrightarrow{M_{${ti}}M_{${tipun}}}|| \\approx ${chiffresSignificatifs(Math.round(x_value[tipun] * Math.pow(10, roundFactor2)) / Math.pow(10, roundFactor2), roundFactor2)} - ${chiffresSignificatifs(Math.round(x_value[ti] * Math.pow(10, roundFactor1)) / Math.pow(10, roundFactor1), roundFactor1)} = ${chiffresSignificatifs(reponse1, nbcs)} \\text{m}$.<br>` + // Soit, après mesure, $||\\overrightarrow{M_{${ti}}M_{${tipun}}}|| = ${chiffresSignificatifs(deplacement, nbcs)} \\text{m}$.<br>` + this.question += `<br>$${miseEnEvidence('c)')}$ En déduire une approximation de la norme du vecteur vitesse $\\overrightarrow{v_{${ti}}}$.<br>` + + // On génère la réponse + reponse2 = reponse1 / tau + this.question += ajouteChampTexteMathLive(this, 3 * i + 2, 'inline largeur01', { texteAvant: 'Norme du vecteur vitesse $\\overrightarrow{v_3}$ = ', texteApres: 'm/s' }) + handleAnswers(this, 3 * i + 2, { reponse: { value: reponse2, compare: approximatelyCompare } })// tolerance de 0.1 + + // On écrit la correction + this.correction += `$${miseEnEvidence('c)')}$ En applicant la relation permettant de calculer l'approximation du vecteur vitesse : $\\overrightarrow{v}\\approx\\frac{\\overrightarrow{M_{${ti}}M_{${tipun}}}}{\\Delta t}$, + on peut approcher la norme du vecteur vitesse par $||\\overrightarrow{v_{${ti}}}||\\approx \\frac{${chiffresSignificatifs(reponse1, nbcs)}\\ \\text{m}}{${chiffresSignificatifs(tau, nbcs)}\\ \\text{s}}=${chiffresSignificatifs(reponse2, nbcs)}\\,\\text{m/s}$. + ` + // fin question + break + case 'confirme': + this.question = `Lors de l'étude d'une vidéo en TP, ${prenom()} observe le déplacement d'un cycliste filmé par un drone. La tête du cycliste est repérée par une croix. <br> + Entre chaque position du cycliste, il se passe ${chiffresSignificatifs(tau, nbcs)} seconde(s). <br>` + // On énonce la question + this.question += this.creerGraphique({ Xmin: xmin, Xmax: xmax, Ymin: ymin, Ymax: ymax, xTickDistance: 1, yTickDistance: 1, fixedWidth }, { tracePoints, labelPoints }) + // this.question += this.creerGraphique({ Xmin, Xmax, Ymin, Ymax, yTickDistance, F }) + this.question += `Déterminer une approximation de la norme du vecteur vitesse $\\overrightarrow{v_{${ti}}}$, au point $M_{${ti}}$.<br>` + // On y ajoute le champ de réponse + this.question += ajouteChampTexteMathLive(this, i, 'inline largeur01', { texteAvant: `Norme du vecteur vitesse $||\\overrightarrow{v_{${ti}}}||=$`, texteApres: 'm/s.' }) + // On génère la réponse + this.reponse = vitesse + // On gère la réponse. Ici, on utilise la fonction approximatelyCompare pour vérifier la valeur de vitesse + handleAnswers(this, i, { reponse: { value: this.reponse, compare: approximatelyCompare } }) + // On écrit la correction + this.correction = `Dans un premier temps, on trace le vecteur déplacement $\\overrightarrow{M_{${ti}}M_{${tipun}}}$ : <br><br>` + + // Ajout du vecteur déplacement + tracePoints.push(vecteurDeplacement) + this.correction += this.creerGraphique({ Xmin: xmin, Xmax: xmax, Ymin: ymin, Ymax: ymax, xTickDistance: 1, yTickDistance: 1, fixedWidth }, { tracePoints, labelPoints }) + + this.correction += ` + Ensuite, il s'agit de mesurer la norme de ce vecteur déplacement, notée $||\\overrightarrow{M_{${ti}}M_{${tipun}}}||$.<br> + Soit, après mesure, $||\\overrightarrow{M_{${ti}}M_{${tipun}}}|| \\approx ${chiffresSignificatifs(deplacement, nbcs)}\\ \\text{m}$.<br> + En applicant la relation permettant de calculer l'approximation du vecteur vitesse : $\\overrightarrow{v}\\approx\\frac{\\overrightarrow{M_{${ti}}M_{${tipun}}}}{\\Delta t}$, + on peut approcher la norme du vecteur vitesse par $||\\overrightarrow{v_{${ti}}}||\\approx \\frac{${chiffresSignificatifs(deplacement, nbcs)}\\ \\text{m}}{${chiffresSignificatifs(tau, nbcs)}\\ \\text{s}}=${chiffresSignificatifs(vitesse, nbcs)}\\,\\text{m/s}$. + ` + // fin question + break + case 'expert': + this.question = `Lors d'une séance de TP, ${prenom()} observe le déplacement d'un palet sur une table horizontale. Le centre de ce palet est repéré par une croix.<br> + Entre chaque position du palet, il se passe ${chiffresSignificatifs(tau, nbcs)} seconde(s). <br>` + // On énonce la question + this.question += this.creerGraphique({ Xmin: xmin, Xmax: xmax, Ymin: ymin, Ymax: ymax, xTickDistance: 1, yTickDistance: 1, fixedWidth }, { tracePoints, labelPoints }) + this.question += `Déterminer une approximation de la norme du vecteur vitesse $\\overrightarrow{v_{${ti}}}$, au point $M_{${ti}}$.<br>` + // On y ajoute le champ de réponse + this.question += ajouteChampTexteMathLive(this, i, 'inline largeur01', { texteAvant: `Norme du vecteur vitesse $||\\overrightarrow{v_{${ti}}}||=$`, texteApres: 'm/s.' }) + // On génère la réponse + this.reponse = vitesse + // On gère la réponse. Ici, on utilise la fonction approximatelyCompare pour vérifier la valeur de vitesse + handleAnswers(this, i, { reponse: { value: this.reponse, compare: approximatelyCompare } }) + // On écrit la correction + this.correction = `Dans un premier temps, on trace le vecteur déplacement $\\overrightarrow{M_{${ti}}M_{${tipun}}}$ :` + + // Ajout du vecteur déplacement + tracePoints.push(vecteurDeplacement) + this.correction += this.creerGraphique({ Xmin: xmin, Xmax: xmax, Ymin: ymin, Ymax: ymax, xTickDistance: 1, yTickDistance: 1, fixedWidth }, { tracePoints, labelPoints }) + + this.correction += ` + Ensuite, il s'agit de mesurer la norme de ce vecteur déplacement $||\\overrightarrow{M_{${ti}}M_{${tipun}}}||$. On peut s'aider d'une règle et d'un tableau de proportionnalité pour déterminer la valeur exacte.<br> + Soit, après mesure, $||\\overrightarrow{M_{${ti}}M_{${tipun}}}|| \\approx ${chiffresSignificatifs(deplacement, nbcs)}\\ \\text{m}$.<br> + En applicant la formule permettant de calculer l'approximation du vecteur vitesse : $\\overrightarrow{v}\\approx\\frac{\\overrightarrow{M_{${ti}}M_{${tipun}}}}{\\Delta t}$, + on peut approcher la norme du vecteur vitesse par $||\\overrightarrow{v_{${ti}}}||\\approx \\frac{${chiffresSignificatifs(deplacement, nbcs)}\\ \\text{m}}{${chiffresSignificatifs(tau, nbcs)}\\ \\text{s}}=${chiffresSignificatifs(vitesse, nbcs)}\\,\\text{m/s}$. + ` + // fin question + break + } + + if (this.questionJamaisPosee(i, a, b, tau)) { // Si la question n'a jamais été posée, on en créé une autre, tgL ne peut pas prendre la même valeur + this.listeQuestions.push(this.question!) // Sinon on enregistre la question dans listeQuestions + this.listeCorrections.push(this.correction!) // On fait pareil pour la correction + i++ // On passe à la question suivante + } + cpt++ // Sinon on incrémente le compteur d'essai pour avoir une question nouvelle + } + + listeQuestionsToContenu(this) // La liste de question et la liste de la correction + } + + // Fonction pour créer le graphique + creerGraphique ({ Xmin, Xmax, Ymin, Ymax, xTickDistance, yTickDistance, xLegende = 'x (m)', yLegende = 'y (m)', fixedWidth }: { Xmin: number, Xmax: number, Ymin: number, Ymax: number, xTickDistance: number, yTickDistance: number, xLegende?: string, yLegende?: string, fixedWidth: number }, propsAdditionnels?: { [key: string]: any } + ) { + // Graphique + const r = repere({ + xMin: Xmin, + xMax: Xmax, + xUnite: 1, + xThickDistance: xTickDistance, // Chez MathAlea, ils appellent ça "thick" mais c'est "tick"... + xLegende, + yMin: Ymin, + yMax: Ymax, + yUnite: 1, + yThickDistance: yTickDistance, // Chez MathAlea, ils appellent ça "thick" mais c'est "tick"... + yLegende, + xLegendePosition: [Xmax / xTickDistance + 1, 0], + yLegendePosition: [0.2, Ymax + 0.5], + grilleSecondaire: true, + // xLabelListe: Array.from({ length: Xmax - Xmin + 1 }, (_, i) => i), + axesEpaisseur: 1.5 + }) + + // Création du graphique + return mathalea2d(Object.assign({ + pixelsParCm: 35, + scale: 2, + style: 'display: block' + }, fixeBordures(r, { + rxmin: 0 + })), r, ...(propsAdditionnels ? Object.values(propsAdditionnels) : [])) + } + + creerGraphique1D ({ Xmin, Xmax, xMajorTickDistance, subdivision, xLegende = 'x (m)', fixedWidth }: { Xmin: number, Xmax: number, xMajorTickDistance: number, subdivision: number, xLegende?: string, fixedWidth: number }, propsAdditionnels?: { [key: string]: any }) { + const A = point(0, 0) + const B = point(fixedWidth, 0) + const laDroite = segment(A, B) + laDroite.styleExtremites = '->' + // Les graduations principales + const graduationsPrincipales: Segment[] = [] + for (let g = 0; g < fixedWidth; g++) { + graduationsPrincipales.push( + segment( + point( + g * xMajorTickDistance, + -0.2 + ), + point( + g * xMajorTickDistance, + +0.2 + ) + ) + ) + } + // Les graduations secondaires + const graduationsSecondaires: Segment[] = [] + for (let g = 0; g < fixedWidth; g++) { + for (let k = 1; k < subdivision; k++) { + const xGraduation = + (g + + k / subdivision) * + xMajorTickDistance + if (xGraduation < B.x) { + graduationsSecondaires.push( + segment(point(xGraduation, -0.1), point(xGraduation, 0.1)) + ) + } + } + } + + // Ajout des labels de graduation principale + const labelsGraduationsPrincipales = [] + const dx = (Xmax - Xmin) / fixedWidth + for (let g = 0; g < fixedWidth; g++) { + const labelRepere1 = latex2d(texNombre(g * dx, 1), g, -0.5, {}) + labelsGraduationsPrincipales.push(labelRepere1) + } + + // Ajout de la légende en bout de droite + const labelLegende = latex2d(xLegende, fixedWidth, -0.5, {}) + labelsGraduationsPrincipales.push(labelLegende) + + // Construction de la droite graduée + const laDroiteGraduee = [ + laDroite, + ...graduationsPrincipales, + ...graduationsSecondaires, + ...labelsGraduationsPrincipales, + ...propsAdditionnels!.tracePoints, + ...propsAdditionnels!.labelPoints + ] + + return mathalea2d( + Object.assign( + { pixelsParCm: 50, scale: 1 }, + fixeBordures(laDroiteGraduee) + ), + laDroiteGraduee + ) + } +} diff --git a/src/json/allExercice.json b/src/json/allExercice.json index 8b20f93d566ad37679bf17f3da6493c16ad35477..52148388e74379ad1c4cc4047acc5b50f6e3197a 100644 --- a/src/json/allExercice.json +++ b/src/json/allExercice.json @@ -309,58 +309,58 @@ }, "2MI1": { "2MI1-1": { - "ref": "2MI-1", + "ref": "2MI1-1", "uuid": "", - "url": "2NDE/2MI-1.js", + "url": "2NDE/2MI1-1.js", "titre": "Identifier les échelles temporelles et spatiales pertinentes de description d’un mouvement.", "tags": {} }, "2MI1-2": { - "ref": "2MI-2", + "ref": "2MI1-2", "uuid": "", - "url": "2NDE/2MI-2.js", + "url": "2NDE/2MI1-2.js", "titre": "Choisir un référentiel pour décrire le mouvement d’un système.", "tags": {} }, "2MI1-3": { - "ref": "2MI-3", + "ref": "2MI1-3", "uuid": "", - "url": "2NDE/2MI-3.js", + "url": "2NDE/2MI1-3.js", "titre": "Expliquer, dans le cas de la translation, l’influence du choix du référentiel sur la description du mouvement d’un système.", "tags": {} }, "2MI1-4": { - "ref": "2MI-4", + "ref": "2MI1-4", "uuid": "", - "url": "2NDE/2MI-4.js", + "url": "2NDE/2MI1-4.js", "titre": "Décrire le mouvement d’un système par celui d’un point et caractériser cette modélisation en termes de perte d’informations.", "tags": {} }, "2MI1-5": { - "ref": "2MI-5", + "ref": "2MI1-5", "uuid": "", - "url": "2NDE/2MI-5.js", + "url": "2NDE/2MI1-5.js", "titre": "Caractériser différentes trajectoires.", "tags": {} }, "2MI1-6": { - "ref": "2MI-6", + "ref": "2MI1-6", "uuid": "", - "url": "2NDE/2MI-6.js", + "url": "2NDE/2MI1-6.js", "titre": "Définir le vecteur vitesse moyenne d’un point.", "tags": {} }, "2MI1-7": { - "ref": "2MI-7", + "ref": "2MI1-7", "uuid": "", - "url": "2NDE/2MI-7.js", + "url": "2NDE/2MI1-7.js", "titre": "Approcher le vecteur vitesse d'un point à l’aide du vecteur déplacement.", "tags": {} }, "2MI1-8": { - "ref": "2MI-8", + "ref": "2MI1-8", "uuid": "", - "url": "2NDE/2MI-8.js", + "url": "2NDE/2MI1-8.js", "titre": "Caractériser un mouvement rectiligne uniforme ou non uniforme.", "tags": {} }