Listes et localisations multiples

Durée estimée: 225 minutes

Présentation :

Cette version de l’application va afficher la localisation de l’utilisateur et d'autres points définis par leur nom, leur adresse, leur type et leur statut.
Ils sont affichés avec une couleur qui dépend du type et du statut, et enregistrés dans deux listes :
une pour leur nom (listeDesTagsDePoints),
l’autre pour leurs données (listeDesDataDePoints ) : latitude, longitude, date/heure, type, statut. La 2° liste est une liste de listes, car chaque item comprend plusieurs attributs.

Ce que vous allez faire :

Cette leçon (sur plusieurs heures) comprend deux parties :
  1. La présentation des notions utilisées (avec des exercices).
    • L’organisation des données et leur structuration avec des listes,
    • Les listes et listes de listes, avec la lecture, l’ajout ou la modification,
    • Les variables locales et leur intérêt par rapport aux variables globales,
    • L’abstraction procédurale,
    • L’utilisation des paramètres dans les procédures,
    • L'organisation du code pour pouvoir s'y retrouver et le relire plus facilement.
  2. La réalisation de la version 2 de l'application avec des listes d’utilisateurs affichés sur la carte avec une couleur qui dépend de leur type et de leur statut. Cette partie comprend sept étapes :
    • Etape 1 : le design et la déclaration des variables globales
    • Etape 2 : mise en place d’outils de contrôle et de debug
    • Etape 3 : affichage des points sur la carte et de la localisation en entête
    • Etape 4 : fonctions d’accès et de contrôle des données
    • Etape 5 : ajout de l’utilisateur dans la liste et affichage localisation en-tête
    • Etape 6 : choix de la couleur pour représenter l’utilisateur
    • Etape 7 : création ou mise à jour de points
C'est une leçon très longue, (sur plusieurs heures) car on est dans la phase du projet où on doit mettre en place les éléments structurants ou le squelette de l'application, dont le modèle des données. Ce modèle utilise des listes et des listes de listes qui sont difficiles. On va aussi mettre en place
  • des procédures qui nous permettront de naviguer dans les données et d'en contrôler la qualité,
  • des outils de "debug" pour journaliser les évènements et disposer de jeux de données tests pour simuler la présence d'autres personnes (même quand on est seul à développer), ...
Gardez en tête que cette application est "compliquée" la version 1 comprend 35 blocs, la version 2 en comprend 750, (vous changez de catégorie) et sa structure vous permettra d'aller beaucoup plus loin.

Ce que vous allez apprendre :

  1. L’organisation des données et leur structuration avec des listes,
  2. La manipulation des listes et liste de listes, avec la lecture, l’ajout ou la modification de points,
  3. L’utilisation de variables locales, leur intérêt par rapport aux variables globales,
  4. L’abstraction procédurale et l’utilisation de procédures de contrôle,
  5. L’utilisation des paramètres dans les procédures,
  6. La manière d'organiser les blocs pour pouvoir les retrouver et les relire plus facilement.

Présentation des Notions utilisées :

Nous vous recommandons de faire une première lecture rapide de cette partie, même si vous maîtrisez déjà assez bien App Inventor. Passez ensuite à la réalisation. Vous reviendrez ensuite à ces notions, au fur et à mesure du besoin.

Variables globales et variables locales :

Vous êtes déjà familiers des variables globales. Elles sont déclarées avec le bloc initialise à l'extérieur de toute fonction ou script. Leur valeur est modifiable à tout moment depuis n’importe quel endroit du programme. C’est pratique, mais c'est dangereux :
  1. une variable globale est modifiable n’importe quand par n’importe quel script ou procédure :
    en cas de problème avec cette variable, on ne saura pas où chercher l’origine du problème,
  2. on finit par avoir beaucoup de variables et ça devient encombrant,
  3. enfin, si on veut travailler à plusieurs en découpant le travail, les variables globales sont partagées. Chacun peut les utiliser ou les interpréter pour faire des choses différentes.

Prenons un exemple :
Dans la première version du programme, on a défini la variable globaleURL.
Où a t-on besoin de cette variable ?
Réponse : dans la procédure AfficherLaCarte, et uniquement dans cette procédure.
Conclusion : Cette variable peut et DOIT être déclarée en variable locale au début de cette procédure.

Les variables globales ont donc mauvaise réputation. Elles ont fait perdre des cheveux à beaucoup de programmeurs. Evitez-les quand elles ne sont pas vraiment nécessaires.
Utilisez plutôt les variables locales qui jouent exactement le même rôle, mais qui ne sont connues qu’à l’intérieur du bloc qui les déclare, donc seulement dans un script ou une procédure. On les déclare quand on en a besoin avec deux blocs. La variable initialisée n’est connue que par les blocs qui sont à l’intérieur du bloc d’initialisation.

La forme de gauche est pratique, au début d’un script pour déclarer les variables dont on aura besoin dans le script.
La forme de droite qui renvoie une valeur, est pratique pour les calculs intermédiaires et dans les fonctions ou procédures qui renvoient une valeur. Nous nous en servirons par exemple pour calculer la distance entre deux points à partir de leurs coordonnées (lat1, long1) et (lat2,long2).
Le rayon de la terre, la distance, les écarts de latitude et longitude sont ici des variables locales utilisées dans les calculs intermédiaires.
Notez que l'on peut déclarer plusieurs variables locales dans un seul bloc.

Constantes et conventions de nommage :

Les constantes sont des données qui ne changent pas pendant l'exécution du programme : le nom de l'application, la taille de l'écran, une donnée de configuration, l'index d'une information spécifique dans une liste, etc.
Par contre, il est utile de désigner les constantes par un nom et de fixer leur valeur à un seul endroit. Par exemple si la variable statut vaut 1 pour un fournisseur et 2 pour un client, on peut définir la constante FOURNISSEUR = 1 et la constante CLIENT = 2. Ensuite, dans le code, on utilisera FOURNISSEUR et CLIENT qui seront explicites et faciles à se rappeler et à comprendre.

App Inventor ne permet pas - contrairement à d'autres langages - de distinguer les variables et les constantes, donc nous ferons cette distinction avec la convention de nommage suivante (qui est courante) :
  • Les constantes sont écrites en majuscule et le caractère de soulignement est utlisé en séparateur, pr exemple INDEX_LAT , APP_NAME ,
  • Les variables commencent par une minuscule et on utilise une majuscule pour identifier le début des mots dans le nom, par exemple listeDesTagsDePoints ou listeDesDataDePoints.
  • Il peut y avoir des exceptions, comme la variable URL, mais il vaut mieux éviter.

Procédures et abstraction procédurale :

Nous avons déjà défini et utilisé la procédure afficherLaCarte dans la version précédente de l'application. Nous allons utiliser les procédures de façon systématique, avec des options nouvelles :

  1. l'utilisation de paramètres dans les procédures,
  2. les procédures qui renvoient une valeur en réponse.

Les procédures peuvent être appelées avec des paramètres et peuvent renvoyer une valeur.
Par exemple : la procédure suivante renvoie la distance entre deux points dont les latitude et longitude sont transmises en paramètres.
Une fonction qui n’utilise pas de variable globale, mais uniquement des paramètres et des variables locales est facile à partager. C’est le cas de la fonction ci-dessus qui calcule la distance en km entre deux points. Vous pouvez l’échanger avec d'autres programmeurs (avec le sac à dos). Comme elle n'utilise pas de variable globale ni de composant, elle est est indépendante du contexte et réutilisable telle quelle.
Dans une procédure :
  • La transmission des informations par les paramètres permet de réduire ou d’éviter l'utilisation des variables globales à l'intérieur des procédures,
  • les paramètres d’appel sont des variables locales de cette procédure,
  • la modification des paramètres d'appel à l'intérieur de la procédure ne modifie PAS la variable utilisée dans le bloc qui appelle cette procédure (sauf dans le cas des listes, cf. ci-dessous).
  • on peut donc manipuler ces variables sans impact sur le reste de l’application,
Attention toutefois à l'utilisation des listes dans les paramètres d'appel (nous y reviendrons plus loin)
  • lorsque le paramètre corrspond à une liste, il porte l'adresse de la liste (et non la liste elle-même),
  • les blocs de listes vont donc modifier la liste désignée par l'adresse en paramètre,
  • donc les blocs de liste - dans une procédure - vont modifier la même liste que celle transmise en paramètre du bloc qui appelle la procédure.

L'abstraction procédurale :

Les procédures permettent de masquer dans un seul bloc, le détail d'une opération complexe, qui peut nécessiter plusieurs dizaines ou centaines de blocs.
Le nom du bloc correspond à la fonction réalisée et permet au lecteur de comprendre ce qui est fait et le résultat renvoyé, sans avoir à se préoccuper du détail de la réalisation : C'est une opération d'abstraction.

Les procédures sont souvent adaptées à la manière dont on décompose un problème pour le résoudre, en commençant par les fonctions de haut niveau. Dans notre cas, les opérations à effectuer au démarrage vont correspondre à une série de procédures :
afficherLaCarte , lireLeProfilUtlisateur , afficherTagEtLocDansHeader , ...

Les procédures permettent également de regrouper - à un seul endroit - les opérations qui sont effectuées plusieurs fois.

  • La procédure afficherLaCarte appelée au démarrage, va aussi être appelée à chaque fois que la localisation change ou que l'on ajoute ou modifie un point. L'utilisation d'une procédure nous évite de dupliquer le code.
  • D'autres procédures - en particulier des procédures de bas niveau - seront utilisées pour naviguer dans les données ou en contrôler la qualité, par exemple :
    • data (tag) qui renvoie la liste des données (data) d'un tag et permet de les modifier
    • tagValide? (tag) qui répond oui ou non selon que le tag est valide ou pas.
    • tagDataValide? (data) qui répond oui ou non selon que les données en paramètre sont des données valides ou pas.

Les listes :

Les listes et les listes de listes sont TRES importantes pour structurer et manipuler les données d’une application.

Dans ce projet, les données décrivent des personnes géo-localisées, ayant des interactions de type client/fournisseur. Il y a plusieurs solutions pour organiser ces données. Elles sont résumées et discutées dans cette vidéo : https://onvaessayer.org/appinventor/?video=listesN2 .

Ici, nous devrons partager les données dans une base de données, donc on va gérer leur nom (ou étiquette, ou tag) dans une première liste et leurs autres données dans une seconde liste.
Comme il y a plusieurs informations par personne, cette seconde liste sera une liste de listes.

Il faut que vous sachiez naviguer dans ces listes de listes, en lecture, puis en écriture ou mise à jour. Vous verrez alors que les listes se comportent différemment des autres variables!

On crée et on manipule ces listes avec des blocs spécifiques.

  • Le numéro d’ordre dans la liste s’appelle l’index.
    Il vaut entre 1 et la longueur de la liste.
  • Une variable de type liste contient l’adresse du contenu de cette liste, pas le contenu lui-même.
    Donc quand on écrit , les deux variables liste1 et liste2 correspondent à un seul et même contenu.
    Pour séparer les contenus, on écrit :
    Nous y reviendrons.

Il y a deux manières principales d’utiliser les listes. Une liste peut désigner :

  • une série de données homogènes, par exemple une liste d’étudiants ou de points,

  • ou la liste des propriétés d’un objet : par exemple
    1. la latitude,
    2. la longitude,
    3. la validité des coordonnées (vrai/faux),
    4. la date et l'heure,
    5. la distance,
    6. etc.

On voit ici deux usages différents des listes.
  • Dans le cas des étudiants on a une liste d’éléments homogènes : les noms.
    La longueur de cette liste va changer régulièrement, avec les arrivées et départs d’étudiants.
  • Dans le cas du point qui est une liste, chaque élément de la liste désigne une propriété différente : latitude, longitude, validité, date, etc.
    Ce sont les propriétés d’une classe d’objets dont la définition sera la même pour tous.
    Cette liste de propriétés est spécifique à l'application et ne va pas changer souvent.
    Dans ce deuxième cas, chaque index 1, 2, 3 ,… correspond à une propriété qui a un sens particulier. Pour s'en souvenir, plutôt que la désigner par un nombre, il est préférable d’utiliser une constante dont le nom permet de se rappeler de quelle propiété il s’agit, par exemple :

Dans le programme pour désigner la latitude, la longitude, nous n’utiliserons JAMAIS le chiffre de son index 1, 2 mais une constante comme INDEX_LAT ou INDEX_LON.
L'utilisation de constantes (i.e. des variables écrites en majuscules) nous permet de nous rappeler du contenu de chaque index, il nous permettra aussi de changer l'ordre, d'ajouter ou de supprimer de nouvelles propriétés. Si vous utilisez des nombres, vous n'arriverez plus à relire votre programme une semaine après l'avoir écrit.

Règle importante

Lorsqu’une liste porte les propriétés ou attributs particuliers d’un objet, n’utilisez jamais des nombres pour désigner un index, mais des CONSTANTES qui permettent de savoir quelle propriété vous manipulez.
App Inventor ne gère pas explicitement les constantes. Donc par convention ici, les constantes sont des variables dont le nom est écrit en majuscules. Pour mémoire, par convention également, les variables commencent par des minuscules avec des majuscules au début de chque mot intermédiaire : c'est la casse en dos de chameau ou "camel case notation".

Voyons maintenant comment créer une liste, lire le contenu à un index, trouver l’index d’un contenu, ajouter ou insérer une nouvelle valeur, supprimer une valeur existante. Il existe des blocs App Inventor pour chacune de ces opérations.

Créer une liste

Créer une liste vide ou
Créer une liste
(Les commandes sont souvent illustrées avec initialise, mais les blocs qui fournissent une valeur peuvent être utilisés avec tous les blocs qui reçoivent une valeur de ce type)

Lecture de la valeur à un index

Lire le nom du 3° étudiant et le mettre dans la variable nom
Lire la date et l’heure de localisation et la mettre dans la variable locTime

Trouver l’index correspondant à une valeur

Lire le nom du 3° étudiant et le mettre dans la variable nom
Lire la date et l’heure de localisation et la mettre dans la variable locTime Dans la liste des étudiants, trouver l’index correspondant à Nassim

Ajouter, insérer, remplacer, supprimer dans une liste

Ajouter Michel à la liste des étudiants
Insérer Jacques à la 2° place dans la liste

(attention, il faut vérifier que la longueur de la liste permet de le faire. On ne peut pas insérer en 4 dans une liste de longueur 2)
Remplacer la valeur à l’index 2 par "Ophélie"

(attention, il faut vérifier que la longueur de la liste est supérieure ou égale à l’index)
Supprimer l’index indexASupprimer de la liste des étudiants.

Noter que l’on a ajouté un test qui vérifie que l’index à supprimer existe
Supprimer "Michel" de la liste des étudiants

Même bloc, on recherche l’index de "Michel" et on fait comme avant (on aurait pu vérifier seulement que l’index n’est pas nul)

Interrogation et contrôle des listes sur leur structure

Cette variable est-elle une liste ?
Cette instruction est généralement utilisée dans un test logique, elle renverra :
  • Faux dans le premier exemple
  • Vrai dans le second
C’est une fonction qui est très importante dans les programmes complexes où il faut vérifier que les variables sont des listes avant de les utiliser comme telles. Les erreurs sur les listes sont parmi les plus fréquentes et souvent très difficiles à analyser.
Ce bloc renvoie la taille de la liste.
Il est très utile, à la suite du précédent, en particu-lier pour éviter des erreurs.
Dans les programmes complexes, il est utile de vérifier que l’index demandé est compris entre 1 et cette taille. Dans le cas contraire, on obtient une erreur souvent difficile à localiser.

Exemple d’utilisation dans un programme

On veut vérifier que la variable mesData contient des données conformes au modèle défini dans la variable modeDePoint (vue plus haut).
On peut le faire avec une procédure qui ren-voie vrai si mesData est conforme, faux sinon.
On vérifie, que c’est une liste puis que sa longueur est la même.

Cette procédure est facile à appeler :

Dupliquer une liste (et son contenu)

Dans cet exemple la liste nouveauPoint, désigne une nouvelle copie du contenu de la liste modeleDePoint.
Les modifications ultérieures apportées à nouveauPoint ne modifieront PAS le contenu de modeleDePoint

Assigner un deuxième nom de variable à la MEME liste

Dans cet exemple la liste nouveauPoint, désigne le même contenu que modeleDePoint. Les modifications de nouveauPoint modifieront AUSSI le contenu de modeleDePoint

Les listes sont très importantes en programmation. Il est essentiel de bien savoir naviguer dans ces listes en lecture, écriture, duplication, etc. Pour ça il faut s’exercer.


Les listes de listes :

Pour présenter les listes de listes, revenons à notre exemple avec une liste de personnes (ou de points)
qui sont géolocalisés et caractérisés par 1. la latitude, 2. la longitude, 3. leur validité, 4. l’heure de mise à jour, 5. la distance, 6. le type et 7. le statut.

C’est à dire avec la liste de propriétés ci-dessous :

Les index de chaque propriété sont rattachés à une constante, qui explicite leur contenu, comme indiqué plus haut.
La liste des points sera alors associée à une liste ou chaque élément contient lui-même une liste de propriétés : On a donc une liste de liste.
A chaque personne ou index dans la listeDesTagsDePoints, Correspond au même index dans la listeDesDataDePoints un jeu ou une liste de données qui décrit ce point ou cette personne.
Dans notre exemple, chaque élément est une liste conforme au modèleDePoints.
Ceci va nous permettre de mettre en œuvre des méthodes de contrôle pour tous les points.


Vous allez à présent faire des exercices de navigation dans la liste des tags de points et la liste de listes des données ou data de ces tags.

  1. Question : Les coordonnées géographiques d’Ophélie sont-elles valides ?
  2. Question : Les coordonnées géographiques d’Alexis sont-elles valides ?
  3. Question : Quel jour et à quelle heure les coordonnées de Wissem ont-elles été mises à jour ?
    Attention : Le code à écrire doit fonctionner même si les listes ont changé (on suppose toutefois que les deux listes sont de même longueur et cohérentes)
  4. Ecrivez la série d’instruction qui récupère l’index de Nassim dans la variable monIndex,
  5. Ecrivez la série d’instructions qui récupère les données d’Alexis dans la liste mesData. Sans que les changements ultérieurs au contenu de la liste mesData ne doit pas affecter la liste initiale
  6. Ecrivez la série d’instructions qui récupère les données d’Alexis dans la liste mesData. mais cette fois, un changement de mesData (par exemple sur la latitude et la longitude) doit être répercuté immédiatement (sans rien écrire) dans la listeDesDataDePoints à l’index d’Alexis
  7. Ecrivez la série d’instruction qui récupère dans la liste listeDesTagsValides de même type que listeDesTagsDePoints, les seuls tags dont la localisation est valide
  8. Ecrivez la série d’instruction qui récupère dans la liste listeDesTagsDeType1 de même type que listeDesTagsDePoints, les seuls tags dont le type est 1.
  9. Ecrivez une procédure verifTagData(var) qui vérifie que la variable var est valide, c’est-à-dire que c’est une liste dont la longueur est la même que le modèle modeleDePoint
  10. Ecrivez la procédure tagData(monTag) qui renvoie la liste de données correspondant au tag monTag si il le trouve et rien (chaine vide) sinon.

Réalisation

Comme indiqué plus haut, la réalisation de la version 2 est d"composée en 7 étapes.
  • 1 : design et déclaration des variables globales
  • 2 : mise en place d’outils de contrôle et de debug
  • 3 : affichage des points sur la carte et de la localisation en entête
  • 4 : fonctions d’accès et de contrôle des données
  • 5 : ajout de l’utilisateur dans la liste et affichage localisation en-tête
  • 6 : choix de la couleur pour représenter l’utilisateur
  • 7 : création ou mise à jour de points
La vidéo suivante (déjà préente plus haut) donne une indication générale, puis une vidéo est fournie pour chaque étape.
Par ailleurs, le code source est fourni, donc ne vous inquiétez pas si vous bloquez, vous pourrez vous rattraper aux branches!

Réalisation : étape 1 - design et variables globales

Ressources en entrée :

Pour cette version de l'application, vous pouvez démarrer à partir de la fin de la version précédente, ou du projet AppInventor à l'adresse suivante : http://ai2.appinventor.mit.edu/?locale=fr_FR&repo=onvaessayer.org/appinventor/uberApp/templates/geolocAppV1/geolocAppV1.asc

Conception

Cette version de l’application doit :

  • définir une liste pour le nom des points et une liste pour leurs donénes (latitude, longitude, ...)
  • créer un premier point pour l’utilisateur et le mettre dans la liste des points,
  • permettre la saisie et l'ajout à la liste de nouveaux points avec leur nom, leur adresse, le type et le statut,
  • convertir l'adresse de chque nouveau point en coordonnées géographiques et l'ajouter à la liste,
    (Tous les points sont décrits de la même manière, avec leur latitude, longitude et d'autres attributs. L’adresse n'est pas prévue)
réafficher la carte après chaque nouveau point ou lorsque la localisation change.

Ca commence à être un peu compliqué et pour avoir une vue d'ensmeble des fonctions à réaliser, on utilise alors des méthodes d'analyse fonctionnelle avec des outils graphiques, pour représenter ce que fait l'application, en particulier avec un diagramme des flux : Les évènements sont représentés par les hexagones jaunes et les principales fonctions par des rectangles. Les flèches nous donnent une indication des enchainements

Chaque évènement va donner lieu à un script.
les fonctions « afficher dans header » et « mettre à jour l’utilisateur dans la liste » seront des procédures appelées depuis l’initialisation et en cas de changement de la localisation.
la fonction d'affichage va changer mlais joue le même rôle.

Design

  • Un titre, avec une icône indiquant le type d’utilisateur, et pour la mise au point un bouton pour le débogage.
  • Une ligne de texte avec le nom et la localisation
  • La carte, avec des boutons pour zoomer, de-zoomer, centrer sur la position de l’utilisateur ou passer en affichage automatique. Le panoramique se fera par glisser sur la carte
  • Zone contextuelle, Profil utilisateur : pour choisir le nom, le type ou les clefs d’API, Ou pour saisir le nom et l’adresse de nouveaux points
  • Ligne pour les messages.
  • Quand l’utilisateur clique sur debug, un arrangement vertical s’affiche en dessous

Composants



Composants applicatifs :

composant Groupe Nom Rôle fonctionnel
label Screen1 Lbl_Header Afficher le nom de l’utilisateur et ses coordonnées
cadre Screen1 Cadre_Carte Cadre1 renommé
Arrangement vertical Screen1 Regroupe lesArgtVert_Input menus pour la saisie des nouveaux points.
Il est invisible au départ, placé sous le cadre de la carte,
Arrangement horizontal ArgtVert_Input ArgtHor_InputAdresse Menus pour l’adresse
Version renommée de l’arrangement vertical1.
Placé dans ArgtVert_Input
Zone de texte ArgtHor_InputAdresse ZoneTxt_Adresse Affichage de l’adressse
Version renommée de Zone_de_texte1 pour afficher l’adresse, dans ArgtHor_InputAdresse
Bouton ArgtHor_InputAdresse Btn_AdresseRecoVocale Déclenchement de la reconnaissance vocale.
Version renommée de Bouton1
Arrangement horizontal ArgtVert_Input ArgtHor_InputNomEtType Pour la saisie du nom, du type et du statut
Label ArgtHor_InputNomEtType Lbl_Nom Zone de texte pour la saisie du nom
(dans l’arrangement précédent)
Zone de texte ArgtHor_InputNomEtType ZoneTxt_Nom Zone de texte pour la saisie du nom
(dans l’arrangement précédent)
Bouton ArgtHor_InputNomEtType Btn_InputType Bouton pour le choix du type : bascule client / fournisseur
(dans l’arrangement précédent)
Bouton ArgtHor_InputNomEtType Btn_InputStatut Bouton pour le choix du statut : bascule libre/ réservé
(dans l’arrangement précédent)
Bouton ArgtHor_InputNomEtType Btn_InputStatut Bouton pour le choix du statut : bascule libre/ réservé
(dans l’arrangement précédent)
Arrangement horizontal ArgtVert_Input ArgtHor_Valider Pour la validation d'un utilisateur (nouveau ou mise à jour)
Bouton ArgtHor_Valider Btn_ValiderNouveauPoint Validation d'un nouvel utilisateur (ou mise à jour)
Bouton ArgtHor_Valider Btn_Debug Activation ou désactivation du mode Debug (journalisation, ...)
Bouton ArgtHor_Valider Btn_DebugVisible Qfficher/masquer les fonctions et informations de debug


Composants pour le debug (en complément des deux deriers boutons) :

composant Groupe Nom Rôle fonctionnel
Arrangement vertical Scroll Screen1 ArgtVertScroll_Debug Arrangement vertical défilant pur debug
Arrangement horizontal Scroll ArgtVertScroll_Debug ArgtHorScroll_Debug Arrangement vertical défilant pur debug
Arrangement horizontal Scroll ArgtHorScroll_Debug Btn_DebugClearDebugText Efface les informations de debug affichaée dans Lbl_Debug
Arrangement horizontal Scroll ArgtHorScroll_Debug Btn_DebugListTags affiche la liste des tags (listeDesTagsDePoints) dans Lbl_Debug
Arrangement horizontal Scroll ArgtHorScroll_Debug Btn_DebugListTagData affiche la liste des données de points (listeDesDataDePoints) dans Lbl_Debug
Arrangement horizontal Scroll ArgtHorScroll_Debug Btn_DebugResetDB Supprime toutes les données (listeDesTagsDePoints, listeDesDataDePoints)
Arrangement horizontal Scroll ArgtHorScroll_Debug Btn_DebugInitListeDePoints ajoute des données à la liste (listeDesTagsDePoints, listeDesDataDePoints)
Arrangement horizontal Scroll ArgtVertScroll_Debug ArgtVert_ScrollDebugLabel Arrangegment vertical défilant pour infos de debug
Arrangement horizontal Scroll ArgtVert_ScrollDebugLabel Lbl_Debug Labbel d'affichage des infos de debug : journal, ...

Programmation : variables globales, évènements, procédures

Variables globales

Variables globales type Contenu
modeleDePoint Modèle de point
listeDesTagsDePoints Liste contenant le nom de chaque point
listeDesDataDePoints Liste donc chaque élément contient les données de chaque point
monTag Nom du tag de l’utilisateur
monType Type de l’utilisateur
mesDataProfil Données ou profil de l’utilisateur (archivées sur les smartphone)
APIKeyMaps Clef du serveur de cartes

Par ailleurs nous allons utiliser des variables pour les opérations de debug :

Variables globales type Contenu
listeInitialeDeTagsPourTests liste noms
listeInitialeDePointsPourTests liste de listes liste de données (conformes au modèle de points)
debug booléen faux
debugVisible booléen faux

Constantes

Nota : la notion de constante n'est pas définie dans App Inventor, mais par analogie avec d'autres langages, nous considèrerons que les variables écrites en lettres capilales sont des constantes.

Pseudo-constantes valeur Contenu
VALEUR_SI_TAG_ABSENT Null valeur renvoyée en cas d’absence d’un tag
PT_INDEX_LAT 1 1 : index de la latitude dans la liste des données d’un point
PT_INDEX_LONG 2 2 : index de la longitude dans la liste des données d’un point
PT_INDEX_A_LONG_LAT 3 3 : index de validité des coordonnées
PT_INDEX_DATE_HEURE 4 4 : index de la date et de l’heure
PT_INDEX_DISTANCE 5 5 : index de la distance en km à l’utilisateur
PT_INDEX_TYPE 6 6 : index du type (Client/Fournisseur)
PT_INDEX_STATUT 7 7 : index du statut (Libre/réservé) les données d’un point
PT_INDEX_MOT_DE_PASSE 8 8 : index du mot de passe dans les données d’un point
PT_INDEX_DESCRIPTION 9 9 : index de la description dans la liste des données d’un point
FOURNISSEUR 1 Valeur à l’index PT_INDEX_TYPE pour un type fournisseur
CLIENT 2 Valeur à l’index PT_INDEX_TYPE pour un type client
LIBRE 1 Valeur à l’index PT_INDEX_STATUT si libre
RESERVE 2 Valeur à l’index PT_INDEX_STATUT si réservé ou indisponible
TXT_FOURNISSEUR Fournisseur Texte utilisé dans l’interface (bouton) pour indiquer un fournisseur
TXT_CLIENT Client Texte utilisé dans l’interface (bouton) pour indiquer un client
TXT_LIBRE Libre Texte utilisé dans l’interface (bouton) pour indiquer libre
TXT_RESERVE réservé Texte utilisé dans l’interface (bouton) pour indiquer réservé
BLANC " " Caractère espace. Utilisé pour éviter la confusion avec NULL
NULL Null Chaine vide. Utilisé pour éviter la confusion visuelle avec BLANC

Evènements

Evènement Rôle fonctionnel
Screen1.Initialize Démarrage de de l’application : appelle start
Capteur_position1.StatusChanged Le changement de localisation va déclencher un rafraichissement des données de l’utilisateur dans la liste (procédure mettreAJourMonTag) et des coordonnées affichées dans l’entête (procédure afficherTagEtLocalisationDansHeader)
Capteur_position1.StatusChanged Idem
ReconnaissanceVocale1.AfterGettingText Met l’adresse dans la ZoneTxt_adresse
Btn_InputType.click Bascule le texte du bouton entre les valeurs TX_CLIENT et TXT_FOURNISSEUR
Btn_InputStatut.click Bascule le texte du bouton entre les valeurs TX_LIBRE et TXT_RESERVE
Btn_ValiderNouveauPoint Vérifie les données d’entrée (nom, adresse, type, statut) :
Vérifie que le nom est valide : TagValide ?
Vérifie la conversion de l’adresse en latitude et longitude
Puis, si valide, ajoute le point orrespondant à la liste
Et appelle afficherLaCarte
Cadre_Carte.Touched Rafraichit la carte par un appel à afficherLaCarte
Screen1.Error Occurred Traite les erreurs sur Screen1, principalement ici la conversion de l’dresse en coordonnées géographiques

Procédure entrées sorties Rôle fonctionnel
start appel les procédures :
setStartSetup :
lireProfilUtilisateurEtCommencer :
setStartSetup configuration des variables et de l’interface de départ
lireProfilUtilisateurEtCommencer renseigne le profil utilisateur,
apppelle mettreAJourMonTag
appelle l’affichage d’entête
puis commencer pour activer la saisie des points.
mettreAJourMonTag(tag,tagData) tag
tagData
Met à jour les données de l’utilisateur dans la liste des points, en particulier avec les coordonnées actuelles
Si l’utilisateur n’existe pas, il est créé dans la liste.
afficherTagEtLocalisationDans Header Affiche en en-tête le nom de l’utilisateur, ses coordon-nées et le mode de localisation
commencer Configure l’interface pour activer la saisie des points,
Puis affiche la carte
afficherLaCarte Affiche la carte avec la liste des points
data(tag) tag Data (liste) Renvoie une variable de type liste qui contient les données du point dont le nom est donné en para-mètre.
Si le nom n’est pas trouvé, une valeur nulle (empty string) est renvoyée.
tagValide ?(tag) tag vrai/faux Renvoie vrai ou faux selon que le nom tag en para-mètre est valide ou pas selon les critères de l’application (chaine de caractères non vide, sans blanc et ne commençant pas par _)
tagDataValide ?(tagData) tagData vrai/faux Renvoie vrai ou faux selon que les données tagData en paramètre sont valides ou pas selon les critères de l’application (liste conforme au modeleDePoint)
tagsEtDataTousValides ? vrai/faux Renvoie vrai si tous les tags et toutes tagData des listes listeDesTagsDePoints et listeDesDataDePoints sont valides. Faux sinon.

Codage de l’application

Déclaration/initialisation des variables globales et des (pseudo)constantes

Organisation des blocs

Initialisation : création de l'utilisateur dans la liste

Création de nouveau point dans les listes (ou mise à jour si existe)

Outils de lecture et de contrôle des données

Afficher ou rafraichir la localisation dans l'entête

Saisir de nouveaux points

Afficher la carte