Outils du site


tutoriels:exo2849

Exemple d'exercice mathenpoche contenant instrumenpoche

Vue de la question 1 corrigée Cet article montre, sur un exemple, comment créer un exercice mathenpoche en utilisant instrumenpoche. L'exercice comporte une correction animée aux instruments virtuels.

L'exercice est un bilan sur les droites remarquables du triangle. Il comporte cinq questions :

  • un triangle aléatoire apparaît,
  • des instruments virtuels de géométrie sont disponibles
  • on demande à l'élève de tracer une droite remarquable de ce triangle.

Si les noms des sommets et leurs emplacements sont aléatoires, les questions ne le sont pas. On doit tracer, dans l'ordre :

  1. la médiatrice d'un côté donné
  2. la médiane relative à un côté donné
  3. la hauteur issue d'un sommet
  4. la bissectrice issue d'un sommet
  5. la hauteur relative à un côté

Préparation

La bibliothèque d'un exercice contenant iep. Il faut créer un fichier flash .fla, télécharger tous les fichiers externes nécessaires à la création d'un exercice en respectant l'arborescence.

Pour instrumenpoche, les composants flash Window, TextArea, RadioButton et NumericStepper sont nécessaires. Pour qu'ils soient disponibles, il faut en placer un de chaque sur la scène, puis le supprimer. Cela aura pour effet de le placer dans la bibliothèque de l'exercice et de le rendre disponible pour instrumenpoche.

Image 1

Le code à mettre en image 1 et les explications pour ce qui concerne instrumenpoche.

Le script

//************************************************************************************************
//**   Ce qu'il y a à personnaliser est là : NE PAS TOUCHER AU RESTE ... la suite en frame 3 !  **
//************************************************************************************************
var nomDeLexo:String = "4G6s3ex1";
var nomDeLAide:String = "modele_aide";
var nombreDeQuestions:Number = 5;
var nombreDeChances:Number = 2;
//la liste des boutons de l'exo :
var liste_boutons:Array = new Array("Valider", "Aide", "Suite");
//Chargement de la calculatrice : true/false
var oncharge_calc:Boolean = false;
//Chargement de TeP : true/false
var oncharge_tep:Boolean = false;
 
/**
Tout ce qui concerne iep (sauf le tableau des clips à charger) se trouve ici
**/
//Chargement de IeP : true/false
var oncharge_iep:Boolean = true;
 
var iep_parametres:Object = new Object();
iep_parametres.liste_instruments =new Array("compas","regle","equerre","crayon");
iep_parametres.boutons_geo = new Array("annuler","restaurer","effacer_tout");
iep_parametres.boutons_lecteur = new Array("debut","precedente","pause","lecture","boucle","suivante","fin");
iep_parametres.options_point_fixe = true;
iep_parametres.options_crayon_droite = true ;
iep_parametres.bord_bas = 275;
var instrumenpoche = _root.createEmptyMovieClip("iep", 92);
instrumenpoche._x=2000;
//FIN IEP
 
 
//
//************************************************************************************************
//************************************************************************************************
//************************************************************************************************
//************************************************************************************************
//************************************************************************************************
//clip accueillant les constantes : NE PAS CHANGER LE NOM !!!
_root.createEmptyMovieClip("exoMeP", 1);
_root.exoMeP.createEmptyMovieClip("clips_externes", 1);
//chargement des clips externes dans "clips_externes
//le loading au niveau 1
var loading = _root.exoMeP.clips_externes.createEmptyMovieClip("loading", 1);
_root.loading._x = 735/2;
_root.loading._y = 450/2;
//les formats au niveau 2
var formats = _root.exoMeP.clips_externes.createEmptyMovieClip("formats", 2);
//les fonctions au niveau 3
var fonctions = _root.exoMeP.clips_externes.createEmptyMovieClip("fonctions", 3);
//le fond au niveau 4
var fond = _root.exoMeP.clips_externes.createEmptyMovieClip("fond", 4);
//la boite de dialogue finale au ninveau 98
var boite = _root.createEmptyMovieClip("clip_boite", 98);
//boite._x = 200;
//boite._y = 30;
//les fonctions de pilotage des outils au ninveau 97
var pilotage = _root.createEmptyMovieClip("pilotage", 97);
 
var traduction = _root.createEmptyMovieClip("traduction", 93);
//////////////////////////////////////////////////////////////////
 
//on définit les clips externes à charger et leur cible
clips_a_charger = new Array(
							["include/loading.swf", _root.loading],
							["include/traduction.swf", _root.traduction],
							["include/formats.swf", _root.formats],
							["include/fonctions.swf", _root.fonctions],
							["include/boite.swf", _root.boite],
							["outils/iep.swf", _root.instrumenpoche],
							["outils/pilotage.swf", _root.pilotage],
							//Charger le fond en dernier sinon il cache le loading
							["include/fond_image.swf", _root.fond])
 
charger_clips(clips_a_charger);
 
//fonction de chargement multiple
var mcl = new Object();
var ecouteur_chargement = new MovieClipLoader();
// l'écouteur pour la progression
mcl.onLoadStart = function (cible_mc) {
	trace("début de chargement de "+cible_mc);
	charger =false;
}
mcl.onLoadComplete = function (cible_mc) {
trace(cible_mc+" est chargé");
charger=true;
}
mcl.onLoadError = function (cible_mc, codeErreur) {
trace("problème de chargement de "+cible_mc+ " : "+codeErreur);
charger=true;
}
ecouteur_chargement.addListener(mcl);
var charger = true;
function charger_clips(tableau:Array) {
   //fonction de chargement multiple
   var n = tableau.length;
   var c = 0;
   _root.onEnterFrame = function(){
	   if(charger){
			clip = tableau[c][0];
			trace(clip)
			if (!((String(clip).indexOf("iep")<>-1) 
                               and (oncharge_iep == false)) and !((String(clip).indexOf("tepnoyau")<>-1) 
                               and (oncharge_tep == false)) and !((String(clip).indexOf("calculatrice")<>-1) 
                               and (oncharge_calc == false))) {
				ecouteur_chargement.loadClip(tableau[c][0],tableau[c][1]);
			}
			c++;
       }if (c >n) {
               trace("FIN DES CHARGEMENTS EXTERNES");
               delete this.onEnterFrame;
               clearInterval(_root.loading.interval);
               removeMovieClip(_root.loading);
               //quand c'est terminé, on passe à la suite.
               play();
        	}
   		}
 
}
var onpatiente:Boolean = false;
//permet de savoir si on a fini de patienter ou non
// permet de temporiser pendant nbsec secondes avant de passer à la fonction suivante (tipe=1)
// ou le temps d'afficher l'aide (tipe=2)
// REMPLACE les CHRONO
function onattend(tipe, nbsec) {
	function attenddeuxsecondes() {
		var arrivee = new Date();
		var secondesa = arrivee.getSeconds();
		if (secondesa>=secondesd) {
			var secondes = secondesa-secondesd;
		} else {
			var secondes = Number(secondesa)+(60-secondesd);
		}
		if (secondes>=nbsec) {
			if (tipe == 0) {
				onpatiente = false;
				clearInterval(kattend);
			}
			if (tipe == 1) {
				clearInterval(kattend);
				fonctions.avance();
			}
			if (tipe == 2) {
				clearInterval(kattend);
				_level100._visible = true;
				correction();
				fonctions.activer_bouton("Suite");
			}
		} else {
			return true;
		}
	}
	var kattend = setInterval(attenddeuxsecondes, 1);
	var depart = new Date();
	var secondesd = depart.getSeconds();
}
stop();

Explications pour iep

La partie concernant instrumenpoche est regroupée vers le début du script :

/**
Tout ce qui concerne iep (sauf le tableau des clips à charger) se trouve ici
**/
//Chargement de IeP : true/false
var oncharge_iep:Boolean = true;
 
var iep_parametres:Object = new Object();
iep_parametres.liste_instruments =new Array("compas","regle","equerre","crayon");
iep_parametres.boutons_geo = new Array("annuler","restaurer","effacer_tout");
iep_parametres.boutons_lecteur = new Array("debut","precedente","pause","lecture","boucle","suivante","fin");
iep_parametres.options_point_fixe = true;
iep_parametres.options_crayon_droite = true ;
iep_parametres.bord_bas = 275;
iep_parametres.mode = "exercice,11";
var instrumenpoche = _root.createEmptyMovieClip("iep", 92);
instrumenpoche._x=2000;
//FIN IEP

Elle débute par

var oncharge_iep:Boolean = true;

qui indique à l'exercice qu'il devra charge instrumenpoche. On a une syntaxe analogue pour les autres outils externes de mathenpoche. Par exemple, ici, on voit que l'exercice ne nécessite pas le chargement de la calculatrice ni de tracenpoche :

//Chargement de la calculatrice : true/false
var oncharge_calc:Boolean = false;
//Chargement de TeP : true/false
var oncharge_tep:Boolean = false;

Ensuite, il faut configurer instrumenpoche, c'est-à-dire lui indiquer quels instruments et boutons seront disponibles. Pour cela on crée un objet qui doit obligatoirement d'appeler iep_parametres. Cet objet peut définir tous les paramètres de la liste des paramètres d'instrumenpoche. Par exemple, ici, on ne donne accès qu'à certains instruments :

iep_parametres.liste_instruments =new Array("compas","regle","equerre","crayon");

avec quelques boutons supplémentaires dans la partie géométrie :

iep_parametres.boutons_geo = new Array("annuler","restaurer","effacer_tout");

Pour la correction, on prévoit de donner accès aux boutons essentiels de lecture d'une animation :

iep_parametres.boutons_lecteur = new Array("debut","precedente","pause","lecture","boucle","suivante","fin");

À noter que ces trois tableaux donnent des listes de boutons dans l'ordre dans lequel ces boutons vont apparaître dans le menu. Si on veut permuter les boutons de la règle et de l'équerre, par exemple, il suffit de permuter leurs position dans le tableau.

Pendant la période de développement, il peut être utile d'ajouter le bouton “script” qui permet à tout moment d'afficher le script iep.

Ensuite viennent différentes options :

iep_parametres.options_point_fixe = true;

qui empêche que les points placés dans instrumenpoche soient déplacés à la souris. En effet, dans cet exercice, l'énoncé sera dessiné dans instrumenpoche, l'élève ne devra pas pourvoir déplacer les sommets du triangle donné.

iep_parametres.options_crayon_droite = true ;

va faire en sorte que les tracés au crayon soient des “droites”, c'est-à-dire des segments dont les extrémités seront sur les bords de la feuille de dessin. Si l'élève utilise le crayon pour tracer un trait entre deux points, cette option va faire en sorte qu'instrumenpoche prolonge le segment passant par ces deux points pour donner l'illusion qu'on a une droite.

iep_parametres.bord_bas = 275;

limite la zone de dessin d'instrumenpoche : on ne peut pas tracer plus bas que 275 pixels depuis le haut de la scène. On peut définir également bord_gauche, bord_droit et bord_haut. Ceci permet de ne pas avoir de tracés sur l'énoncé. Par défaut, instrumenpoche donne accès à toute la place disponible.

var instrumenpoche = _root.createEmptyMovieClip("iep", 92);

Création du clip dans lequel mathenpoche va charger iep.swf. Le niveau 92 est réservé à instrumenpoche dans mathenpoche, il faut donc le conserver. Attention : ne pas nommer le clip Instrumenpoche (avec une majuscule) qui est un nom de classe utilisé dans instrumenpoche, il pourrait y avoir des conflits et des bugs.

instrumenpoche._x=2000;

On place le clip de chargement hors de la scène par souci d'esthétique : lorsque les divers chargements sont un peu longs, on risque de voir apparaître les différents outils (le temps que le chargement se fasse), puis les voir disparaître.

Image 3

Le script contenu dans l'image 2 ne doit pas être modifié. L'image 3 va servir à définir l'énoncé des questions de l'exercice.

Mise en place de l'énoncé dans mep

Un code habituel dans les exercices de mathenpoche, qui permet de tout effacer entre deux questions :

fonctions.initialiser_exo();
fonctions.viderMovieClips();

Ensuite, on génère trois lettres au hasard (les noms des sommets du triangle) et trois points également aléatoires. Ce code n'est pas spécifique à intrumenpoche, nous ne nous y attarderons pas. Remarquons simplement qu'il définit des variables utiles pour la suite :

  • lettre1, lettre2 et lettre3 : les noms des sommets
  • xa, ya, xb, yb, xc et yc : les coordonnées des sommets
// on choisit trois lettres de l'alphabet au hasard
code = [];
for (i=1; i<4; i++) {
	code[i] = random(26)+65;
	for (j=1; j<i; j++) {
		if (code[i] == code[j]) {
			i = i-1;
		}
	}
}
var lettre1 = String.fromCharCode(code[1]);
var lettre2 = String.fromCharCode(code[2]);
var lettre3 = String.fromCharCode(code[3]);
 
//emplacement des points du triangle
ok = false;
while (ok == false) {
	ok = true;
	x = random(100)+50;
	xa = 365-x;
	xb = 365+x;
	e = random(2)+1;
	p = Math.pow(-1, e);
	xc = p*random(100)+365;
	ya = 140+random(50)+p*30;
	yb = 140+random(50)-p*30;
	yc = random(40)+40;
	if (ya == yb or xa == xc or xc == xb or Math.abs((ya+yb)/2-yc)<10 or Math.abs((yc+yb)/2-ya)<10 or (xa+xb)/2 == xc) {
		ok = false;
	}
}

Ceci étant fait, on affiche l'énoncé comme d'habitude dans un exercice de mathenpoche. Suivant les questions, il faut passer un (si on demande la droite issue d'un sommet) ou deux (droite relative à un côté) paramètres ) la fonction creer_texte_dynamique :

_root.btn.Valider_btn.tabIndex = _root.nb_saisie+1;
_root.btn.Suite_btn.tabIndex = _root.nb_saisie+2;
//Affichage du n° de la question à l'aide de la fonction creer_texte : 
fonctions.creer_texte_dynamique(_root,"question",10,"affichage_question",10,280,0,0,trad[2][12],[numquestions]);
if (numquestions == 3 || numquestions == 4) {
	fonctions.creer_texte_dynamique(_root,"consigne",12,"zone_consigne",
                               affichage_question._x,affichage_question._y+affichage_question._height+3,0,0,
                               _root.trad2[5][numquestions],[lettre1]);
} else {
	fonctions.creer_texte_dynamique(_root,"consigne",12,"zone_consigne",
                               affichage_question._x,affichage_question._y+affichage_question._height+3,0,0,
                               _root.trad2[5][numquestions],[lettre1, lettre2]);
}
//on dessine le cadre de l'énoncé :
fonctions.tracer_cadre_consigne(5,affichage_question._y-5,725,65);

Affichage d'iep

Il faut ensuite montrer instrumenpoche puis, si nécessaire, le passer en mode géométrie en donnant accès aux instruments :

// je montre iep
instrumenpoche._visible = true;
// si iep n'est pas en mode géométrie, je l'y mets :
if(!Instrumenpoche.geometrie){
	Instrumenpoche.permuter();
	}
instrumenpoche.iep.menu_geo._visible = true;

Il faut bien distinguer instrumenpoche, qui est le nom variable du clip dans lequel on a chargé iep et Instrumenpoche (avec majuscule), qui est un mot réservé à iep.

instrumenpoche._visible = true;

rend visible le clip instrumenpoche.

La classe Instrumenpoche contient une variable, nommée geometrie, qui dit si on est en mode de création aux instruments ou non. Cette variable vaut true lorsqu'on est en mode de création et à false en mode lecture. Ici, si on est en mode lecture (par exemple après avoir visualisé la correction de l'exercice précédent), on passe en mode création. Cela se fait par la fonction Instrumenpoche.permuter() qui permet de passer d'un mode à l'autre.

La dernière ligne affiche le menu donnant accès aux instruments, toujours pour le cas où il aurait été masqué lors d'une correction.

Script iep de la figure de l'énoncé

Ensuite, on va dessiner la figure de l'énoncé avec instrumenpoche. Pour cela, il faut créer un script de construction géométrique. On peut, en concaténant des textes, lui passer les paramètres de l'exercice (coordonnées et noms des points).

Le script est un texte. Pour plus de clarté, on va le créer ligne par ligne.

La première ligne consiste à amener le crayon sur le point de coordonnées xa,ya, les paramètres définis plus haut :

script_pour_iep = "<action id='1' mouvement='translation' objet='crayon' abscisse='"+xa+"' ordonnee='"+ya+"' />"

Par exemple, si xa=200 et ya=150, le code ci-dessus donnera pour script_pour_iep un texte égal à <action id='1' mouvement='translation' objet='crayon' abscisse='200' ordonnee='150' />

Il faut bien prendre garde aux guillemets. En effet, on a besoin de guillemets :

  • dans actionscript, pour encadre le texte qui sera un script iep ;
  • dans iep, pour encadrer les valeurs des attributs (comme objet=“crayon” par exemple).

Pour cela, on a deux types de guillemets : ' et . Il faut en choisir un pour actionscript et un autre pour iep.

Maintenant que le crayon est sur le premier sommet, on lui fait tracer le triangle :

script_pour_iep +="<action id='2' mouvement='tracer' couleur='0x666666' objet='crayon' abscisse='"+xb+"' ordonnee='"+yb+"' />"
script_pour_iep +="<action id='3' mouvement='tracer' couleur='0x666666' objet='crayon' abscisse='"+xc+"' ordonnee='"+yc+"' />"
script_pour_iep +="<action id='4' mouvement='tracer' couleur='0x666666' objet='crayon' abscisse='"+xa+"' ordonnee='"+ya+"' />"

puis on crée des points instrumenpoche aux sommets du triangle, on les nomme et on replace le crayon :

script_pour_iep +="<action id='5' mouvement='creer' couleur='0x666666' objet='point' abscisse='"+xa+"' ordonnee='"+ya+"' />"
script_pour_iep +="<action id='6' mouvement='creer' couleur='0x666666' objet='point' abscisse='"+xb+"' ordonnee='"+yb+"' />"
script_pour_iep +="<action id='7' mouvement='creer' couleur='0x666666' objet='point' abscisse='"+xc+"' ordonnee='"+yc+"' />"
script_pour_iep +="<action id='5' mouvement='nommer' couleur='0x666666' objet='point' nom='"+lettre1+"' />"
script_pour_iep +="<action id='6' mouvement='nommer' couleur='0x666666' objet='point' nom='"+lettre2+"' />"
script_pour_iep +="<action id='7' mouvement='nommer' couleur='0x666666' objet='point' nom='"+lettre3+"' />"
script_pour_iep +="<action mouvement='translation' objet='crayon' abscisse='"+abscisse_init+"' ordonnee='"+ordonnee_init+"' />";

La variable Instrumenpoche.image_direct a deux effets :

  • elle indique à iep après quelle action il doit se caler pour l'affichage de la figure ;
  • elle bloque le bouton “annuler” et empêche qu'on efface ainsi l'énoncé.

Il faut donc définir cette variable à la longueur totale du script qu'on vient de créer :

Instrumenpoche.image_direct = (new XML(script_pour_iep)).childNodes.length;

La fonction LecteurIep.lecture_apres_chargement ordonne à iep d'afficher la construction. On lui passe en paramètre un objet qui peut contenir un texte anim décrivant la figure et éventuellement un texte config pour la configuration. ici, la configuration a été définie en image 1, car elle ne change pas d'une question à l'autre.

LecteurIep.lecture_apres_chargement({anim:"<INSTRUMENPOCHE version='2'>"+script_pour_iep+"</INSTRUMENPOCHE>"});

Image 4

Après un

stop();

le code de l'image 4 consiste essentiellement en deux fonctions :

  • une fonction valider() qui vérifie si la réponse donnée par l'élève est juste et gère l'affichage des messages ;
  • une fonction correction(), appelée par la précédente en cas de double erreur, qui crée un script iep permettant de montrer une correction animée de l'exercice aux instruments virtuels.

Fonction valider

On déclare une fonction qui doit se nommer valider, nom de la fonction systématiquement appelée par le bouton “valider” de mathenpoche :

function valider() {

Cette fonction va effectuer des tests sur le script de la figure tracée par l'élève. Elle va donc souvent se servir des fonctions de test définies dans TestIep.as.

La première chose à faire est de vérifier si l'élève a donné une réponse correspondant au moins grossièrement à la question. Ici, il faut savoir si une droite au moins a été tracée. On écrit le code suivant :

	// test de la validité de la réponse avant de passer aux tests
	valide = (TestIep.est_dans_iep({objet:"longueur_segment_crayon", longueur:500, precision:498})>3);

qui crée une variable valide, qui sera égale à true si et seulement si le script d'instrumenpoche contient au moins 4 (d'ou le >3) segments tracés au crayon dont la longueur est égale à 500 pixels, à 498 pixels près. Soit des segments compris entre 2 et 998 pixels de long, ce qui devrait suffire pour détecter les tracés de segments en évitant les doubles clics maladroits. Pourquoi 4 ? Parce que le test porte sur tout le script d'iep : énoncé et construction de l'élève compris, et l'énoncé comporte déjà 3 tracés de segments au crayon pour le triangle.

Par défaut, la validation masque le menu d'instrumenpoche, il faut donc le montrer (on remarque que, plus haut, on a pu écrire instrumenpoche. et ici iep., qui sont synonymes).

	iep.iep.menu_geo._visible = true;

Pour la validation, il va falloir tester si une certaine droite a été tracée. Pour cela, il faut connaître deux points de cette droite, dont les coordonnées seront transmises à la fonction de test et nommées xpoint1, ypoint1, xpoint2 et ypoint2.

Question 1 : Coordonnées de deux points de la médiatrice, dont le milieu

	if (numquestions == 1) {
		// médiatrice
		xpoint1 = (xa+xb)/2;
		ypoint1 = (ya+yb)/2;
		xpoint2 = xpoint1+50;
		ypoint2 = ypoint1+50*(xb-xa)/(ya-yb);
	} 

Question 2 : Coordonnées de deux points de la médiane : le milieu d'un côté et le sommet opposé

else if (numquestions == 2) {
		// médiane
		xpoint1 = (xa+xb)/2;
		ypoint1 = (ya+yb)/2;
		xpoint2 = xc;
		ypoint2 = yc;
	}

Question 3 : Hauteur

else if (numquestions == 3) {
		// hauteur sommet
		xpoint1 = xa;
		ypoint1 = ya;
		xpoint2 = xa+50;
		ypoint2 = ya+50*(xb-xc)/(yc-yb);
	}

Question 4 : Bissectrice

On utilise une fonction utilitaire de fonctions.swf (voir dans fonctions.fla les fonctions disponibles).

 else if (numquestions == 4) {
		// bissectrice
		xpoint1 = xa;
		ypoint1 = ya;
		var angle1 = fonctions.mesure_angle(xc, yc, xa, ya, xb, yb)/2;
		var angle2 = fonctions.mesure_angle(xa+50, ya, xa, ya, xc, yc);
		var angle = angle1+angle2;
		trace("angle de la bissectrice : "+angle1+"  "+angle2+" soit : "+angle);
		xpoint2 = xa+200;
		ypoint2 = ya+200*Math.tan(angle*Math.PI/180);
	}

Question 5 : Hauteur

 else if (numquestions == 5) {
		// hauteur côté
		xpoint1 = xc;
		ypoint1 = yc;
		xpoint2 = xc+50;
		ypoint2 = yc+50*(xb-xa)/(ya-yb);
	}

Ensuite, on teste si la bonne droite a été tracée avec iep. Il faut passer les coordonnées des points qu'on vient de calculer.

	var bonne_reponse = (TestIep.est_dans_iep({objet:"droite_crayon", 
                      abscisse1:xpoint1, ordonnee1:ypoint1, abscisse2:xpoint2, ordonnee2:ypoint2, 
                      ecart_angle:2}) == 1);

Si une droite quelconque a été tracée, on procède à la vérification et à l'affichage des messages. Cette partie est habituelle dans les exercices mathenpoche et indépendante d'intrumenpoche.

	if (valide) {
		_root.occupe = true;
		_root.fonctions.desactiver_bouton("Valider");
		if (bonne_reponse == true) {
			// si c'est bon :
			_root.juste = true;
			if (_root.nbr_reponse == 0) {
				// si la première réponse est la bonne :
				fonctions.indication(_root.trad[4][1],formats.format_bravo);
			} else if (_root.nbr_reponse == 1) {
				// si juste après une erreur :
				fonctions.indication(_root.trad[4][2],formats.format_bien);
			}
			//on affiche le score :         
			fonctions.afficher_score();
			_root.suite = 1;
		} else {
			// si c'est faux :
			_root.juste = false;
			if (_root.nbr_reponse == 0) {
				// en cas de première erreur :
				_root.nbr_reponse++;
				_root.erreur1++;
				message_indication = _root.trad[4][4];
				if (_root.nbr_reponse>=_root.fonctions.configuration.aide_apparition) {
					message_indication += _root.trad[4][139];
				}
				fonctions.indication(message_indication,formats.format_faux);
				//activation des boutons
				_root.fonctions.activer_bouton("Valider");
				_root.occupe = false;
			} else {
				// en cas de deuxième erreur :
				_root.nbr_reponse++;
				if (_root.numquestions != _root.nbre_questions) {
					//si ce n'est pas la dernière question,
					message_indication = _root.trad[4][5];
					if (_root.nbr_reponse>=_root.fonctions.configuration.aide_apparition) {
						message_indication += _root.trad[4][150];
					}
					fonctions.indication(message_indication,formats.format_faux);
					//l'appel de onattend permet de temporiser avant d'ouvrir l'aide et de corriger
					onattend(2,2);
				} else {
					//si c'est la dernière question, on temporise, 
                                        //on corrige et on passe à la suite (on n'ouvre pas l'aide automatiquement)
					_root.correction();
					_root.suite = 1;
				}
				//on affiche le score (suivant la configuration chargée) :
				fonctions.afficher_score();
			}
			//on affiche l'aide (suivant la configuration chargée) :
			fonctions.afficher_aide();
		}
		//envoi du résultat de l'avancement des travaux de l'élève à l'interface réseau :
		commphp();
	} else {
		message_indication = _root.trad2[6][1];
		fonctions.indication(message_indication,formats.format_faux);
	}
}

Fonction correction

Lorsque l'élève a répondu, instrumenpoche contient un script qui décrit l'énoncé de la question puis la construction effectuée. La fonction correction() consiste à ajouter, à la suite de ce script, des actions qui construisent la droite attendue.

Pour éviter des calculs trop ardus, on va utiliser la classe MacroIep.as. Comme son nom l'indique, cette classe contient des “macros”. Ce sont des fonctions qui, lorsqu'on leur passe des paramètres, renvoie un script instrumenpoche correspondant à la construction voulue, ainsi que d'autres paramètres qui peuvent être utiles.

Ici, nous allons utiliser plusieurs fois la fonction MacroIep.placer_point_equidistant.

Cette fonction construit au compas un point équidistant de deux autres dont les coordonnées sont passées en paramètres. Elle renvoie un tableau [script de la construction, abscisse du point construit, ordonnée du point construit], ce qui permet de récupérer les coordonnées de ce point pour un usage ultérieur. Il est également possible de lui passer des paramètres facultatifs, comme la couleur du trait, son épaisseur ou l'identifiant de point tracé.

Au début de la fonction de correction, on défini Instrumenpoche.image_direct sur le nombre d'étapes que contient le script énoncé+construction de l'élève. Cela aura pour effet, lors de la lecture de la correction, de bloquer le début du visionnage à la fin de cette construction : ce qui a été fait avant la correction sera toujours affiché.

// Fonction de correction :
function correction() {
	Instrumenpoche.image_direct = ScriptIep.code_xml.firstChild.childNodes.length;

On récupère le script instrumenpoche dans un texte. ScriptIep.code_xml contient tout le script iep. Le code suivant permet de ne récupérer que les nœuds action, sans l'en-tête ni la partie <INSTRUMENPOCHE>.

	var	texte = ScriptIep.code_xml.firstChild.childNodes.join("");

Première question (médiatrice)

La première chose à faire est de masque tous les instruments, sauf le compas qui va nous servir.

	// on masque les instrus qui peuvent gêner éventuellement
	if(numquestions==1){
	texte+="<action mouvement='masquer' objet='crayon' />";
	texte+="<action mouvement='masquer' objet='equerre' />";
	texte+="<action mouvement='masquer' objet='regle' />";
	texte+="<action mouvement='montrer' objet='compas'/>";

Pour tracer la médiatrice à l'aide du compas, on utilise la fonction MacroIep.placer_point_equidistant. Il faut lui passer en paramètres les coordonnées des deux extrémités du segment dont on veut la médiatrice. Ensuite, on peut lui passer un objet, qui contient ici :

  • id1 et id2 (les identifiants des arcs de cercles tracés),
  • distance est ajouté à la demi-distance entre les extrémités : les arcs de cercle auront un rayon égal à la demi-distance entre les extrémités, plus 10 pixels.
  • couleur et epaisseur sont définis conformément à la charte graphique des exercices mathenpoche

Cette fonction renvoie un tableau, dont la première partie est une portion de script iep qui correspond au tracé des deux arcs de cercle. On ajoute ce morceau de script à notre texte :

	var tab = MacroIep.placer_point_equidistant(xb,yb,xa,ya,{id1:53, id2:54, 
                                   distance:10, couleur: 0x006600, epaisseur:2});
	texte += tab[0];

Le tableau renvoyé par MacroIep.placer_point_equidistant est de la forme [script de la construction, abscisse du point construit, ordonnée du point construit]. On peut donc récupérer les coordonnées de l'intersection des arcs de cercle pour y placer un point nommé. Le nom de ce texte sera en fait une phrase : “Ce point est équidistant de … et …”, où les pointillés sont remplacés par les noms des sommets de l'énoncé.

	texte+="<action mouvement='creer' objet='point' id='11' abscisse='"+tab[1]+"' ordonnee='"+tab[2]+"' couleur='0x006600' />"
	texte += "<action mouvement ='nommer' objet='point' id='11' 
                          nom='"+fonctions.recuperation_texte(trad2[7][11],[lettre1,lettre2])+"' 
                          taille='10' couleur='0x006600' tempo='40' />";

On masque le message puis on passe au deuxième point équidistant et on affiche le même message que précédemment, mais sur le nouveau point.

Remarque : par défaut, MacroIep.placer_point_equidistant fait en sorte que le triangle formé par les deux points donnés en arguments et le point résultat soit direct. Ci-dessus, le code MacroIep.placer_point_equidistant(xb,yb,xa,ya… traçait un point équidistant d'un côté du segment, alors que ci-dessous MacroIep.placer_point_equidistant(xa,ya,xb,yb… va tracer un point de l'autre côté, car on a inversé l'ordre des points. De ce côté-ci, on peut se permettre un distance:60 (il faut avoir prévu la place lors du tracé aléatoire du triangle, tout au début).

	texte +="<action mouvement='masquer' objet='point' id='11' />"
	tab = MacroIep.placer_point_equidistant(xa,ya,xb,yb,{id1:51, id2:52, 
                            distance:60, couleur: 0x006600, epaisseur:2});
	texte += tab[0];
	texte+="<action mouvement='masquer' objet='compas' />";
	texte+="<action mouvement='creer' objet='point' id='12' 
                       abscisse='"+tab[1]+"' ordonnee='"+tab[2]+"' couleur='0x006600' />";
	texte += "<action mouvement ='nommer' objet='point' id='12' 
                       nom='"+fonctions.recuperation_texte(trad2[7][11],[lettre1,lettre2])+"' 
                       taille='10' couleur='0x006600' tempo='40' />";
	texte += "<action mouvement ='nommer' objet='point' id='12' nom='"+trad2[7][18]+"' 
                       taille='10' couleur='0x006600' tempo='40' />";

Ensuite, on trace la médiatrice à la règle :

	texte+="<action mouvement='montrer' objet='regle' />";
	texte+="<action mouvement='translation' objet='regle' cible='12' />";
	texte+="<action mouvement='rotation' objet='regle' cible='11' />";
	texte+="<action mouvement='montrer' objet='crayon' />";
	texte+="<action mouvement='translation' objet='crayon' cible='12' />";
	texte+="<action mouvement='tracer' objet='crayon' cible='11' id='35' 
                         forme='droite' couleur='0x006600' epaisseur='2' />";

Ici, nous avons utilisé l'attribut cible, mais nous aurions aussi bien pu nous servir des coordonnées préalablement mises en mémoire.

On ajoute des explications animées sur le fait que la médiatrice est perpendiculaire au segment et passe par son milieu :

	texte+="<action mouvement='masquer' objet='crayon' />";
	texte+="<action mouvement='masquer' objet='regle' />";
	texte+="<action mouvement='masquer' objet='point' id='12' />"
	texte+="<action mouvement='montrer' objet='equerre' />";
	texte+="<action mouvement='translation' objet='equerre' cible='5' />";
	texte+="<action mouvement='rotation' objet='equerre' cible='6' />";
	texte+="<action mouvement='translation' objet='equerre' abscisse='"+(xa+xb)/2+"' 
                         ordonnee='"+(ya+yb)/2+"' />";
	texte+="<action mouvement='creer' objet='texte' id='55' abscisse='50' ordonnee='50' />";
	texte+="<action mouvement='ecrire' objet='texte' id='55' 
                         texte='"+fonctions.recuperation_texte(trad2[7][12],[lettre1,lettre2])+"' 
                         taille='15' couleur='0x006600' tempo='40' />";
	texte+=MacroIep.creer_codage_angle_droit(xb,yb,(xa+xb)/2,(ya+yb)/2,tab[1],tab[2],{couleur:0x006600});
	texte+="<action mouvement='masquer' objet='equerre' />";
	texte+="<action mouvement='montrer' objet='regle' />";
	texte+="<action mouvement='translation' objet='regle' cible='5' />";
	texte+="<action mouvement='rotation' objet='regle' cible='6' />";
	texte+="<action mouvement='creer' objet='texte' id='52' abscisse='56' ordonnee='100' />";
	texte+="<action mouvement='ecrire' objet='texte' id='52' texte='"+trad2[7][13]+"' 
                         taille='15' couleur='0x006600' tempo='40' />";
	texte+="<action mouvement='masquer' objet='regle' />";
	texte+="<action mouvement='creer' objet='longueur' forme='///' 
                         abscisse='"+(xb+3*xa)/4+"' ordonnee='"+(yb+3*ya)/4+"' id='61' couleur='0x006600' />";
	texte+="<action mouvement='creer' objet='longueur' forme='///' abscisse='"+(xa+3*xb)/4+"' 
                         ordonnee='"+(ya+3*yb)/4+"' id='62' couleur='0x006600' />";
}

Pour cette fin de code, la nouveauté est la fonction MacroIep.creer_codage_angle_droit qui, lorsqu'on lui passe les coordonnées de trois points A, B et C, renvoie le code instrumenpoche pour ajouter un codage d'angle droit sur l'angle ABC.

Deuxième question (médiane)

La correction de la deuxième question est plus simple que la précédente : les deux points importants sont un sommet du triangle initial (dont on a les coordonnées xc et yc) et le milieu du côté opposé, dont les coordonnées se calculent sans besoin d'appel à la classe MacroIep. Le script est le suivant :

else if(numquestions==2){
	texte+="<action mouvement='masquer' objet='crayon' />";
	texte+="<action mouvement='masquer' objet='equerre' />";	
	texte+="<action mouvement='masquer' objet='compas' />";
	texte+="<action mouvement='montrer' objet='regle' />";
	texte+="<action mouvement='translation' objet='regle' cible='5' />";
	texte+="<action mouvement='rotation' objet='regle' cible='6' />";
	texte+="<action mouvement='creer' objet='point' id='11' 
                     abscisse='"+(xa+xb)/2+"' ordonnee='"+(ya+yb)/2+"' tempo='30' />";
	texte+="<action mouvement='masquer' objet='regle' />";
	texte+="<action mouvement='nommer' objet='point' id='11' couleur='0x006600' taille='10' 
                     nom='"+fonctions.recuperation_texte(trad2[7][14],[lettre1,lettre2])+"' tempo='30' />";
	texte+="<action mouvement='montrer' objet='regle' />";
	texte+="<action mouvement='translation' objet='regle' cible='11' />";
	texte+="<action mouvement='creer' objet='point' id='12' abscisse='"+xc+"' ordonnee='"+yc+"' tempo='30' />";
	texte+="<action mouvement='nommer' objet='point' id='12' couleur='0x006600' 
                     taille='10' nom='"+trad2[7][15]+"' tempo='30' />";
	texte+="<action mouvement='rotation' objet='regle' cible='7' />";
	texte+="<action mouvement='montrer' objet='crayon' />";
	texte+="<action mouvement='translation' objet='crayon' cible='11' />";
	texte+="<action mouvement='tracer' id='31' objet='crayon' cible='7' 
                     forme='droite' epaisseur='2' couleur='0x006600' />";
	texte+="<action mouvement='masquer' objet='crayon' />";
	texte+="<action mouvement='masquer' objet='regle' />";

On peut coder des longueurs égales dans instrumenpoche. On place ces codages respectivement au quart et aux trois-quarts de la longueur du segment :

	texte+="<action mouvement='creer' objet='longueur' forme='///' 
                        abscisse='"+(xb+3*xa)/4+"' ordonnee='"+(yb+3*ya)/4+"' 
                        id='61' couleur='0x006600' />";
	texte+="<action mouvement='creer' objet='longueur' forme='///' 
                        abscisse='"+(xa+3*xb)/4+"' ordonnee='"+(ya+3*yb)/4+"' 
                        id='62' couleur='0x006600' />";
	}

Troisième et cinquième questions (hauteurs)

Les questions 3 et 5 concernent les hauteurs. Il n'y a pas de difficulté particulière si on a compris comment fonctionne le script d'instrumenpoche. Cependant, il faut calculer les coordonnées du pied de la hauteur. Dans ce tels cas, il est utile de fouiller dans fonctions.fla qui regorge d'utilitaires en géométrie, comme fonctions.proj_ortho qui, si on lui passe les coordonnées de trois points, renvoie les coordonnées du projeté orthogonal du premier point sur la droite passant par les deux autres.

else if(numquestions==3 || numquestions ==5){
	texte+="<action mouvement='masquer' objet='crayon' />";		
        texte+="<action mouvement='masquer' objet='regle' />";
	texte+="<action mouvement='masquer' objet='compas' />";
	texte+="<action mouvement='montrer' objet='equerre' />";	
        texte+="<action mouvement='translation' objet='equerre' cible='5' />";
	texte+="<action mouvement='rotation' objet='equerre' cible='6' />";
	texte+="<action mouvement='creer' objet='texte' id='51' abscisse='50' ordonnee='50' />";
	texte+="<action mouvement='ecrire' objet='texte' id='51' 
                       texte='"+fonctions.recuperation_texte(trad2[7][16],[lettre1,lettre2])+"' 
                       taille='15' couleur='0x006600' tempo='40' />";
	var tab = fonctions.proj_ortho(xc, yc, xa, ya, xb, yb);
	texte+="<action mouvement='creer' objet='texte' id='52' abscisse='50' ordonnee='100' />";
	texte+="<action mouvement='ecrire' objet='texte' id='52' 
                        texte='"+fonctions.recuperation_texte(trad2[7][17],[lettre3])+"' 
                        taille='15' couleur='0x006600' tempo='40' />";
	texte+="<action mouvement='translation' objet='equerre' abscisse='"+tab[0]+"' ordonnee='"+tab[1]+"' />";
	texte+="<action mouvement='montrer' objet='crayon' />";
	texte+="<action mouvement='translation' objet='crayon' abscisse='"+tab[0]+"' ordonnee='"+tab[1]+"' />";
	texte+="<action mouvement='tracer' objet='crayon' id='51' abscisse='"+xc+"' ordonnee='"+yc+"' 
                        couleur='0x006600' epaisseur='2' forme='droite' />";
	texte+="<action mouvement='masquer' objet='crayon' />";
	texte+="<action mouvement='masquer' objet='equerre' />";			
}

Quatrième question

Pour la correction de la quatrième question (la bissectrice), il va falloir, en supposant que les points se nomment W, Q et B comme sur la figure ci-contre :

  1. tracer un arc de cercle de centre W qui coupe les segments [WQ] et [WB] ;
  2. repérer les points d'intersection ;
  3. tracer un point équidistant de ces deux points ;
  4. tracer la droite passant par W et ce point équidistant.

On commence par masquer tous les instruments, sauf le compas qui doit être visible :

else{
	texte+="<action mouvement='masquer' objet='crayon' />";
	texte+="<action mouvement='masquer' objet='regle' />";
	texte+="<action mouvement='masquer' objet='equerre' />";

Il faut calculer les angles que forment les deux côtés du triangle qui nous intéressent avec l'horizontale. Pour cela, on utilise la fonction Math.atan2 d'actionscript :

	var angle1 = Math.atan2(yb-ya,xb-xa)*180/Math.PI;
	var angle2 = Math.atan2(yc-ya,xc-xa)*180/Math.PI;

On positionne le compas sur le sommet :

	texte +="<action mouvement='montrer' objet='compas' />";
	texte +="<action mouvement='translation' objet='compas' cible='5' />";

L'arc de cercle qu'on va tracer doit intercepter les deux côtés. Son rayon doit donc être inférieur à ces deux côtés. On le fixe égal au plus petit côté moins 30 pixels :

	var eca = (Math.min(CalculIep.distance(xa,ya,xb,yb),CalculIep.distance(xa,ya,xc,yc))-30);
	texte +="<action mouvement='ecarter' objet='compas' ecart='"+(eca)+"' />";

Comme l'arc de cercle doit “déborder” des côtés, on remplace le plus petit des angles précédents par sa valeur moins dix degrés et le plus grand par sa valeur plus dix degrés :

	var sens;
	if(angle1<angle2){
		angle1 -=10		
                angle2 +=10;
		sens = 5;
	}else{
		angle1 +=10;
		angle2 -=10;
		sens = -5;
	}

Le compas trace cet arc de cercle (prendre garde à définir correctement le sens pour le tracé) :

	texte+="<action mouvement='rotation' objet='compas' angle='"+(angle1)+"' sens='5' />";
	texte +="<action mouvement='lever' objet='compas' />";
	texte+="<action mouvement='tracer' objet='compas' debut='"+(angle1)+"' fin='"+(angle2)+"' 
                        couleur='0x006600' epaisseur='2' sens='"+sens+"' id='51' />";
	texte +="<action mouvement='coucher' objet='compas' />";

La fonction CalculIep.point_sur_droite renvoie les coordonnées du point voulu : le point M situé sur une droite (AB) et tel que la mesure algébrique AM soit égale à une certaine valeur (ici, la valeur est eca) :

	var tab1 = CalculIep.point_sur_droite(xa,ya,xb,yb,eca);
	var tab2 = CalculIep.point_sur_droite(xa,ya,xc,yc,eca);

On utilise MacroIep pour générer le code de tracé d'un point équidistant des intersections au compas :

	tab = MacroIep.placer_point_equidistant(tab2[0],tab2[1],tab1[0],tab1[1],
                        {id1:53, id2:52, couleur: 0x006600, epaisseur:2});
	texte += tab[0];
	texte +="<action mouvement='masquer' objet='compas' />";

On trace la bissectrice. Les coordonnées du deuxième point de la bissectrice sont dans le tableau tab défini ci-dessus. Pour pivoter la règle sans refaire de calcul, le plus simple est d'utiliser l'attribut cible ;

	texte+="<action mouvement='montrer' objet='regle' />";
	texte+="<action mouvement='translation' objet='regle' abscisse='"+tab[1]+"' ordonnee='"+tab[2]+"' />";
	texte+="<action mouvement='rotation' objet='regle' cible='5' />";
	texte+="<action mouvement='montrer' objet='crayon' />";
	texte+="<action mouvement='translation' objet='crayon' abscisse='"+xa+"' ordonnee='"+ya+"' />";
	texte+="<action mouvement='tracer' objet='crayon' id='54' abscisse='"+tab[1]+"' 
                        ordonnee='"+tab[2]+"' couleur='0x006600' epaisseur='2' forme='droite' />";
	texte+="<action mouvement='masquer' objet='crayon' />";
	texte+="<action mouvement='masquer' objet='regle' />";

Enfin, on crée un codage d'angle isntrumenpoche. Là encore, les calculs d'angles peuvent être assez délicats. Une macro MacroIep.creer_codage_angle permet de générer le code :

	texte+=MacroIep.creer_codage_angle(xc,yc,xa,ya,tab[1],tab[2],{couleur:0x006600,rayon:35,forme:"plein/"});
	texte+=MacroIep.creer_codage_angle(tab[1],tab[2],xa,ya,xb,yb,{couleur:0x006600,rayon:40,forme:"plein/"});
}

On passe à cette fonction les coordonnées de trois points A, B et C pour générer le codage de l'ange ABC. Il est possible de passer des options de dessin dans un objet supplémentaire. Ici, on fixe la couleur verte de la correction, deux rayons différents afin que les codages soient distincts et une forme “plein/” qui va colorier l'intérieur du codage, avec un / sur l'arc de cercle.

Finalisation

Une fois les actions décrites dans la variable texte, on crée un script instrumenpoche au format XML :

	ScriptIep.code_xml = new XML("<INSTRUMENPOCHE version='2'>"+texte+"</INSTRUMENPOCHE>");

On règle Instrumenpoche.image_fin à la longueur du script, afin d'indiquer à iep qu'il peut faire afficher toutes les étapes.

	Instrumenpoche.image_fin = ScriptIep.code_xml.firstChild.childNodes.length;

Puis on passe en mode lecture, étant entendu que la fonction correction n'est appelée que lorsque instrumenpoche est en mode de création aux instruments. Sinon, il aurait fallu faire un test comme on l'a fait en image 3.

	Instrumenpoche.permuter();	

La fin de la fonction correction est classique : on affiche le bouton “suite” sauf si c'est la dernière question :

	if (_root.numquestions<_root.nbre_questions) {
		_root.exoSuite = true;
		fonctions.indication(_root.trad[4][6],formats.format_faux);
	} else {
		fonctions.indication(_root.trad[4][7],formats.format_faux);
	}
}

Le script de cet exercice se termine par la fonction “onattend” habituelle.

// la fonction onattend permet de temporiser et de passer à la suite en lançant la fontion "avance()" ... lorsque suite = 1
_root.onEnterFrame = function() {
	if (_root.suite == 1) {
		onattend(1,2);
		_root.suite = 0;
	}
};
tutoriels/exo2849.txt · Dernière modification : 31/12/2010 15:20 de 127.0.0.1