Différences entre versions de « Tutoriel:Éviter des tâches répétitives en éditant le code XML »

De GeoGebra Manual
Aller à : navigation, rechercher
(an)
Ligne 64 : Ligne 64 :
 
On peut alors placer les boules: dans la version initiale, c'étaient des listes de points, maintenant cela doit être des points indépendants. Je vais d'abord créer la liste de la première tige (centaines de mille), et la dupliquer dans le code XML.
 
On peut alors placer les boules: dans la version initiale, c'étaient des listes de points, maintenant cela doit être des points indépendants. Je vais d'abord créer la liste de la première tige (centaines de mille), et la dupliquer dans le code XML.
  
Ces points s'appelleront A0 (boule du haut), A1 ... A4 (boules du bas).
+
Ces points s'appelleront A0 (boule du haut), A1 ... A4 (boules du bas). Je crée ces 5 points comme points de la tige puis je change leurs valeurs avec SoitValeur.
<code>A_0=(1,7-nh_1)]
 
  
A_1=(1,Si[nb_1==0,3,4])]
+
<code>SoitValeur[A_0,(1,7-nh_1)]
  
A_2=(1,Si[nb_1<=1,2,3])]
+
SoitValeur[A_1,(1,Si[nb_1==0,3,4])]
  
A_3=(1,Si[nb_1<=2,1,2])]
+
SoitValeur[A_2,(1,Si[nb_1<=1,2,3])]
  
A_4=(1,Si[nb_1<=3,0,1])]
+
SoitValeur[A_3,(1,Si[nb_1<=2,1,2])]
 +
 
 +
SoitValeur[A_4,(1,Si[nb_1<=3,0,1])]
 
</code>
 
</code>
  
* <code>A_1 = (1,)</code>
+
{{note|1=On aurait pu faire ça avec une commande Exécute/Séquence ... mais ça devient barbare!}}
  
On crée donc:
+
{{note|Pourquoi d'abord créer les points puis les modifier avec SoitValeur, au lieu de les créer directement avec = ? J'ai envie que ces points aient comme définition: point de la tige, et que l'utilisateur ne puisse pas les changer de tige. SoitValeur se contente de modifier la valeur, pas la définition initiale.}}

Version du 29 octobre 2013 à 22:42

S'éviter des tâches répétitives en éditant le code XML

Objectif

Ce tutoriel est né d'une appliquette qui m'a fait créer une quarantaine de points, tous munis d'un script au clic: il s'agit d'un boulier où l'on peut interagir dans deux sens:

  • On choisit un entier grâce à des boutons et une zone de texte (entier tapé, entier choisi au hasard, entier choisi dans une liste): le boulier affiche alors cet entier.
  • On clique sur les boules du bouliers pour les déplacer, l'entier correspondant s'affiche alors en écriture décimale.

Chaque boule est représentée par un (gros) point muni d'un script; le but de ce tutoriel est de présenter un moyen de rentrer cette quarantaine de scripts sans devenir fou! Un bon éditeur de texte et de la concentration suffisent...

Le boulier présente plein d'avantages pour enseigner la numération en école primaire ou au début du collège: il permet de plus des exercices de calcul mental, et permet d'apprendre à poser les additions et les soustractions. Mais cela revient beaucoup moins cher de disposer d'un boulier geogebra plutôt que d'acheter autant de bouliers que d'élèves! Le boulier choisi est de type Soroban, avec sur chaque tige, 5 boules valant l'unité (en bas) et une boule valant 5 (en haut). Les boules sont activées lorsqu'elles sont poussées contre la barre centrale. Voici le produit fini.

J'ai fait une première version du boulier où les boules étaient gérées par des listes de points. Il est assez facile de déterminer quelles boules doivent être activées en fonction de l'entier à afficher. C'est un peu de manipulation de la division entière. Ce faisant on arrive facilement à coder la première partie de l'interaction: on choisit un entier, on définit quatre listes dépendant de cet entier: les boules du bas activées, les boules du bas désactivées, les boules du haut activées, les boules du haut désactivées. Quelques commandes Séquence permettent d'afficher les points correspondants au bon endroit et le tour est joué (voir la section suivante). Mais coder l'interaction dans l'autre sens (déplacer les boules pour changer l'entier) demande de récupérer, dans un script, sur quel élément d'une liste on a cliqué. Or, j'ai cherché, demandé dans les forums, et sauf erreur de ma part, cette fonctionnalité n'existe pas dans geogebra. Il a donc fallu faire une version où chaque boule est un point indépendant muni d'un script. D'où le problème: comment éditer facilement un grand nombre de scripts, qui se ressemblent tous à des différences d'indice prêt? En l'absence d'une commande 'SoitScript', on est obligés de passer par le menu propriété->scripts et de rentrer tous les scripts un par un, soit un nombre considérable de manipulations à la souris. Il faut être particulièrement zen et patient pour mener cette tâche sans oublier une boule ou sans se tromper sur l'édition d'un script.

Il y a heureusement moyen de modifier un fichier geogebra via un éditeur de texte: on édite en fait un fichier XML à la structure relativement claire. On rentre alors les scripts directement dans le code XML à l'aide de votre éditeur de texte favori, dont vous maîtrisez la fonction 'chercher/remplacer'.

Les sections qui suivent présentent:

  • la mise en place du boulier avec des listes de points
  • l'adaptation, à l'aide de commandes "Exécute" de cette première version pour obtenir des points indépendants.
  • l'édition des scripts via le code XML.

Première mise en place avec des listes de points

La figure ci-dessous illustre le rendu graphique souhaité:

Boulier interactif disposition.png

  • La tige des unités est en x=6, celle des dizaines en x=5, ..., celle des centaines de mille en x=1.
  • Pour les boules du haut: elles sont activées en y=6, désactivées en y=7.
  • Pour les boules du bas: elles occupent les ordonnées entières, de y=0 (contre la barre du bas) à y=4 (contre la barre centrale).

Si n est l'entier à afficher (0 <= n <= 999999) , on peut obtenir sa liste de chiffres par: listechiffres=Retourner[Séquence[Quotient[Reste[n,10^i], 10^(i - 1)], i, 1, 6]].

Liste pour les boules du bas: listebas=Séquence[Reste[Elément[listechiffres, i], 5], i, 1, 6]. Liste pour les boules du haut: listehaut=Séquence[Quotient[Elément[listechiffres, i], 5], i, 1, 6]. Ces listes indiquent, pour chaque tige, combien de boules sont activées en bas et en haut.

Liste des boules du haut: listeptshaut=Séquence[(i, 7- (Elément[listehaut, i])), i, 1, 6]: ainsi les boules du haut sont positionnées soit en (i,7) (pas de boule activée pour la ième tige) soit en (i,6) (boule activée pour la ième tige).

Liste des boules du bas activées : listeptsbas1=Séquence[Séquence[(i, 5-j), j, 1, Elément[listebas, i]], i, 1, 6]: ainsi les boules du bas activées de la ième tige sont placées en (i,4), (i,3), (i,2), (i,1).

Liste des boules du bas désactivées: listeptsbas2=Séquence[Séquence[(i, j-1), j, 1, 4 - Elément[listebas, i]], i, 1, 6]: ainsi les boules du bas désactivées de la ième tige sont placées en (i,0), (i,1), (i,2), (i,3).

La mise en place est terminée, ainsi que l'interaction entier décimal vers boulier: il suffit de changer la valeur de n pour que les boules prennent automatiquement la bonne position: à vous de créer des boutons et zones de textes pour régler n, et de dessiner le boulier. Il reste encore à régler l'interaction dans l'autre sens.

Les limites des scripts pour les listes : recréer la construction avec la commande Exécute

On peut associer un script (au clic, à l'actualisation) à une liste d'objets. Pour, par exemple, un script au clic, l'effet est que le script sera activé dès lors qu'on clique sur un élément de la liste. Mais, sauf erreur de ma part, il n'existe pas de moyen de récupérer dans le script sur quel élément de la liste on a cliqué.

Or, mon idée était que lorsqu'on clique sur une boule (par ex: une boule désactivée du bas), on modifie par script la valeur de n: si cette boule est la première du tas, alors on fait n=n+1 (tige des unités), n=n+100 (tige des centaines), et l'affichage suit automatiquement via les listes dépendantes de n. Mais pour cela il faut savoir:

  • sur quelle tige on a cliqué (indice i des séquences)
  • pour les boules du bas, savoir si on a cliqué sur un élément qu'on peut bouger: celui du bas pour les boules activées, celui du haut pour les boules désactivées.

Je vais donc refaire l'application avec, au lieu de listes, des nombres et points indépendants crées avec la commande Exécute. Cela permet de réutiliser le travail fait avec des listes, mais en créant des points indépendants. Pour faciliter le copier/coller ultérieur sous XML, je crée des noms logiques: la liste de chiffres (listechiffres) devient par n1, n2, n3...par la commande:

  • Exécute[ Séquence[ "n_"+(7-i)+" = Div[ Mod[ n , 10^"+(i)+"] , 10^"+(i-1)+" ]" , i , 1, 6 ]]

La liste du nombre de boules activées en haut devient les nombres nh1, nh2, ... par:

  • Exécute[ Séquence[ "nh_"+i+" = Div[n_"+i+",5]" , i , 1, 6 ]]

La liste du nombre de boules activées en bas devient les nombres nb1, nb2, .... par:

  • Exécute[ Séquence[ "nb_"+i+" = Mod[n_"+i+",5]" , i , 1, 6 ]]
Note : La commande Exécute prend en argument une liste de chaînes de caractères, qu'elle fait exécuter par geogebra. Je suis donc parti d'une commande Séquence initiale, qui crée une liste, j'ai mis entre guillemets son premier argument, j'ai rajouté n= au début, puis à chaque fois que la valeur de i doit apparaître, je brise la chaîne et j'utilise l'opérateur + (concaténation de chaînes).

. Ces trois commandes créent, au lieu de trois listes de nombres, les nombres n1, n2, ..., nh1, nh2, ..., nb1, nb2, ...

Note : Il faut faire attention que les commandes arguments de Exécute (donc ce qui est entre guillemets) doivent être en anglais: Quotient est ainsi devenu Div, Reste est devenu Mod. Utiliser le wiki, section commandes, en français pour trouver votre commande, puis changer la langue (menu en haut à droite de la page) pour avoir son nom anglais.

On peut alors placer les boules: dans la version initiale, c'étaient des listes de points, maintenant cela doit être des points indépendants. Je vais d'abord créer la liste de la première tige (centaines de mille), et la dupliquer dans le code XML.

Ces points s'appelleront A0 (boule du haut), A1 ... A4 (boules du bas). Je crée ces 5 points comme points de la tige puis je change leurs valeurs avec SoitValeur.

SoitValeur[A_0,(1,7-nh_1)]

SoitValeur[A_1,(1,Si[nb_1==0,3,4])]

SoitValeur[A_2,(1,Si[nb_1<=1,2,3])]

SoitValeur[A_3,(1,Si[nb_1<=2,1,2])]

SoitValeur[A_4,(1,Si[nb_1<=3,0,1])]

Note : On aurait pu faire ça avec une commande Exécute/Séquence ... mais ça devient barbare!
Note : 
© 2024 International GeoGebra Institute