Affichage des articles dont le libellé est Débutant. Afficher tous les articles
Affichage des articles dont le libellé est Débutant. Afficher tous les articles

samedi 25 novembre 2017

Editeur des diagrammes Entité/Association en une soirée grace à Processing

La facilité de dessin et de gestion des évènement permet au développeur sous Processing de préparer rapidement des prototypes ou bien des outils dans un temps record. Cette capacité est très nécessaire lorsqu'il s'agit de prouver une idée ou bien pour préparer une démonstration rapide pour votre client.

Dans cet exemple, j'ai créé rapidement un éditeur des diagramme Entité/Association sous Processing dans environs 350 lignes de code. L'éditeur ne permet pas d'annuler, de déplacer de sélectionner les objets créés. Néanmoisn, il permet de :
  1. Créer des entités en faisant un clique gauche :
    1. L'entité est créée à l'endroit où le clique a eu lieu.
    2. L'éditeur vous demande le nom de l'entité qui ne doit pas être vide.
    3. Il vous demande, par la suite, une liste d'attributs, une à la fois. La création de la liste des attributs s'arrête lorsque la chaîne vide est entrée.
  2. Créer des associations en faisant un clique droit :
    1. L'association est créée à l'endroit où le clique a eu lieu.
    2. L'éditeur vous demande le nom de l'association qui ne doit pas être vide.
    3. Il vous demande, par la suite, une liste d'attributs, une à la fois. La création de la liste des attributs s'arrête lorsque la chaîne vide est entrée.
  3. Pour créer un lien, il faut dessiner une ligne d'un objet à un autre objet de différente nature (d'une entité vers une association ou bien d'une association vers une entité). Les autres liens seront refusés (l'unique vérification dans le système).
Au stade actuel, le système ne fait pas d'autres vérifications, c'est à dire, il est possible de créer deux entités avec le même nom, d'avoir deux attributs identiques et de mettre ce que vous voulez comme cardinalité. Mais, comme j'ai déjà mentionné, il s'agit d'une démo pour Processing plus qu'un éditeur.

Dans ce projet, vous pouvez voir comment différencier les bouttons de la souris en toute simplicit. Dans la méthode "mousePressed()", il est nécessaire de vérifier est ce qu'il s'agit d'un clique droit pour insérer une association ou bien d'un clique gaucheoù il faut véirifier est ce qu'il est appliqué à l'intérieur d'un objet ce qui veut dire qu'il s'agit d'un lien ou bien s'il est à l'extérieur de tout objet pour insérer une nouvelle entité.

void mousePressed(){
  if(mouseButton == LEFT){
    int entite = verifierEntites(mouseX, mouseY);
    if(entite != -1){
      creationLien = true;
      entiteSource = true;
      source = entite;
    }else{
      int association = verifierAssociations(mouseX, mouseY);
      if(association != -1){
        creationLien = true;
        entiteSource = false;
        source = association;
      }else{
        lireEntite(mouseX, mouseY);
      }
    }
  }else{
    lireAssociation(mouseX, mouseY);
  }
}

La vérification que le clique est à l'intérieur d'un objet se fait par rapport aux coordonnés et mesures de ce dernier. Ainsi dans la classe Objet, on trouve la méthode "estDedans()" :

  public boolean estDedans(int cx, int cy){
    return cx > x && cx < x + getLargeur() && cy > y && cy < y + getHauteur();
  }

La méthode qui est supposée faire toutes les vérifications concerant les noms des entitées, des associations et des attributs ne fait en réalité que lire ces valeurs sans aucune vérification; elle nécessite un effort supplémentaire :


void lireEntite(int mx, int my){
  String nom = JOptionPane.showInputDialog(null, "Donnez le nom de l'entité");
  if(nom != null && !nom.equals("")){
    Entite e = new Entite(mx, my);
    String propriete;
    int i = 0;
    do{
      propriete = JOptionPane.showInputDialog(null, "Donnez les propriétés (vide pour terminer)");
      if(propriete != null && !propriete.equals("")){
        e.addAttribut(propriete);
        i++;
      }
    }while(propriete != null && !propriete.equals("") && i < NOMBRE_MAX_ENTITES);
    e.setNom(nom);
    entites[nbrEntites] = e;
    nbrEntites++;
  }
}


Vous pouvez télécharger le code par ici.

Drag & Drop sous Processing en quelques lignes

L'interactivité sous Processing est très impressionnates. En quelque lignes, il est possible de récupérer et traiter les différents évènements prevenant de la souris ou bien du clavier. Cet exemple vise à donner un avant-goût de ces capacités.
Le Drag Drop consiste à lever un objet en cliquant dessus, le déplacer (le voir se déplacer) en gardant le clique et le déposer en relâchant le clique.

Sous Processing, nous pouvons exploiter les éléments suivants :
  •  Il est à tout moement possible de récupérer la position de la souris grâce à deux variables prédéfinies : museX, mouseY. Aucun code ou fonction ou Listener sont nécessaires.
  • Pour récupérer l'évènement du clique, il suffit d'implémenter la méthode "mousePressed()"; elle sera appelée si l'un des deux bouttons de la souris est enfoncé. mouseBoutton permet de connaître est ce qu'il s'agit d'un clique droit (RIGHT) u gauche (LEFT).
  • Pour récupérer l'évènement du relâche de la souris, il suffit d'implémenter la méthode "mouseReleased()".
Le seul élément que nous allons ajouter est une variable booléenne pour garder trace est ce que l'objet est entrain d'être déplacé ou pas. Le code suivant est le code de l'objet (nommé Activite, préparé dans un contexte précis) :

class Activite {
  
  int x, y;
  final int HEIGHT = 180;
  final int WIDTH = 180;
  
  public Activite(int x, int y){
    this.x = x;
    this.y = y;
  }
  
  void draw(){
    rect(x, y, HEIGHT, WIDTH);
  }
  
  void setX(int x){
    this.x= x;
  }
  
  void setY(int y){
    this.y = y;
  }
  
  int getX(){
    return x;
  }
  
  int getY(){
    return y;
  }
  
}

Ce code est presque un JavaBean, à l'exception de la méthode draw() qui déssine un rectangle.
Le code du Drag & Drop est :

Activite a;

int diffx, diffy;
boolean drawing = false;

void setup(){ 
  size(960, 480);
  a = new Activite(100, 100);
}

void draw(){
  background(240);
  
  if(drawing){
    a.setX(mouseX + diffx);
    a.setY(mouseY + diffy);
  }
  
  a.draw();
}

void mousePressed(){
  diffx = a.getX() - mouseX;
  diffy = a.getY() - mouseY;
  drawing = true;
}

void mouseReleased(){
  drawing = false;
}

Les deux variables diffx et diffy c'est pour garder la distance entre la position de la souris et la position de l'objet au départ de l'action.

Une version abrégée de ce code peut montrer qu'il est possible d'implémenter le tout avec toutes les données et les fonctions en moins de 30 lignes en gardant notre code claire at aéré:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int x, y, h, w;
int diffx, diffy;
boolean drawing = false;

void setup(){ 
  size(960, 480);
  x = 100; y = 100;
  h = 100; w = 250;
}

void draw(){
  background(240);
  if(drawing){
    x = mouseX + diffx;
    y = mouseY + diffy;
  }  
  rect(x, y, w, h);
}

void mousePressed(){
  diffx = x - mouseX;
  diffy = y - mouseY;
  drawing = true;
}

void mouseReleased(){
  drawing = false;
}

Chute libre dans le vide sous Processing

Simuler une phénomène naturel en utilisantl'animation est un moyen excellent pour l'enseigner et pour l'expliquer. Cette approche permet, aussi, de modifier les différents paramètres et voir les différents scénarios possibles avec un coût (pratiquement) nul.
Dans cet exemple, nous allons simuler une chute libre dans le vide. Pour rendre la simualtion un peu plus réel, nous allons ajouter un effet de rebond par définir un facteur de préservation de l'énergie au moement de l'impact au sol.
L'objet en question est une boule. Elle sera définie comme un objet séparé pour donner la possibilité de comparer plsuieurs chutes avec des paramètres différents.
Le problème peut être modélisé suivant deux approches :
  • L'utilisation des équations en fontion du temps "t", la position et la vitesse de l'objet seront calculées en fontion de l'instant "t" de l'animation.
  • En utilisant des suites pour la vitesse te la position. Les paramètres de l'instant "t" seront obtenus en fontion des paramètres de l'instant "t - 1".
Dans cet exemple, nousa allons suivre cette deuxième approche. Le passage d'un instant à l'instant suivant est implémenté sous la forme d'une fonction que nous appelerons chaque intervalle du temps (un autre paramètre que nous pouvons modifier à notre guise).

 


Le code principal est très simple. Il initialise l'environnement et déclare une boule. Chaque fois, il dessine la boule avec sa position, sa vitesse et son énergie.


Boule b;

void setup(){
  size(600, 400);
  b = new Boule(100, 0, 50, 10, 0.9f);
}

void draw(){
  background(255);
  b.draw();
  if(frameCount % 6 == 0)
    b.instantSuivant();
  fill(0);
  text("" + b.getVitesse(), 10, 30);
  text("" + b.getEnergie(), 10, 50);
  text("" + b.getY(), 10, 70);
};

Le code  de l'objet Boule permet de garder les différentes information de la boule, de simuler la chute et de déssiner la boule :


class Boule {
  
  public final static float G = 1f;
  
  float preservation;
  int x, y, diametre, vitesse, masse, energie;
  
  public Boule(int x, int y, int diametre, int masse, float preservation){
    this.x = x;
    this.y = y;
    this.diametre = diametre;
    this.masse = masse;
    this.preservation = preservation;
  }
  
  public void instantSuivant(){
    y += vitesse;
    energie = masse * vitesse * vitesse / 2;
    if(y >= height - diametre / 2){
      vitesse = (int)(-1 * preservation * Math.sqrt(2 * energie / masse));
    }else{
      vitesse += G;
    }
  }
  
  public void draw(){
    fill(255);
    stroke(0);
    ellipse(x, y, diametre, diametre);
  }
  
  public int getVitesse(){
    return vitesse;
  }
  
  public int getEnergie(){
    return energie;
  }
  
  public int getY(){
    return y;
  }
  
  public int getX(){
    return x;
  }
    
  
}

La fonction qui nous intéresse le plus est la fonction "instantSuivant()". Elle montre le changement appliqué sur la vitesse :


  public void instantSuivant(){
    y += vitesse;
    energie = masse * vitesse * vitesse / 2;
    if(y >= height - diametre / 2){
      vitesse = (int)(-1 * preservation * Math.sqrt(2 * energie / masse));
    }else{
      vitesse += G;
    }
  }

  • Si l'objet est en chute, la vitesse est influencée par la gravité seulement.
  • Si la boule touche le sol, la gravité n'est plus appliquée mais c'est le rebond qui repousse la boule vers le haut.
 
L'état final de l'animation est la boule immobile au fon d de l'écran (le sol).
Nous pouvons facilement ajouter une autre boule pour comparer les deux chutes :


Boule b1, b2;

void setup(){
  size(600, 400);
  b1 = new Boule(100, 0, 50, 10, 0.9f);
  b2 = new Boule(200, 0, 80, 10, 0.5f);
}

void draw(){
  background(255);
  b1.draw();
  b2.draw();
  if(frameCount % 6 == 0){
    b1.instantSuivant();
    b2.instantSuivant();
  }
  fill(0);
  text("b1", 10, 10);
  text("" + b1.getVitesse(), 10, 30);
  text("" + b1.getEnergie(), 10, 50);
  text("" + b1.getY(), 10, 70);
  text("b2", 10, 90);
  text("" + b2.getVitesse(), 10, 110);
  text("" + b2.getEnergie(), 10, 130);
  text("" + b2.getY(), 10, 150);
};


mardi 14 février 2017

Ecrire des outils personnels, pourquoi est-ce important ?

Il est possible, aujourd'hui, de trouver toute sorte de logiciel sur le marché. De plus petit utilitaire au plus grand logiciel, les offres se multiplient, soit pour les logiciels payants, soit pour les logiciels Open Source. Il est même possible de faire appel aux outils en ligne, suivant (presque) la philosophie de SAAS. Ainsi, il est possible d'utiliser des outils pour dessiner des graphes, prendre des notes ou même écrire et compiler des programmes sans rien installer sur la machine.
Néanmoins, nous nous trouvons des fois face à des problématiques particulières, ou bien, face à des exigences particulières imposées par notre propre environnement de travail et la combinaison unique des logiciels installés et leur utilisation dans le cadre de notre propre activité quotidienne. Cette combinaison est, à mon avis, unique et c'est pourquoi le phénomène "Work on my machine" est toujours présent entre les développeurs.
Cet environnement unique nécessite, par conséquent, une configuration unique. Il faut adapter les différents outils et logiciels ainsi que le système d'exploitation installé pour répondre à nos exigences particulières. Ainsi, nous nous trouvons entrain de lire les différentes ressources de documentation, de visiter les sites dédiés des logiciels installer et sauter entre les différents dossiers pour modifier tel ou tel fichier en ajoutant des commandes par ci et en "dé-commentant" une ligne par là.
Une situation plus délicate est le passage d'un système à un autre; dans l'état actuel des choses, ces actions de configuration manuelle sont (pratiquement) impossibles à transmettre entre l'ancienne version et la nouvelle version (ou l'ancien environnement et le nouvel environnement). Ma récente expérience avec une mise à niveau majeure de mon système m'a fait vivre cette situation avec tous ses détails : j'étais obligé de reprendre l'installation de mes outils à zéro (chose qui n'est pas vraiment pénible), en plus, il fallait les configurer. J'étais, à titre d'exemple, surpris de voir mon installation locale de la plateforme Moodle s'arrêter malgré le respect des différentes consignes et après plusieurs heures de vérification j'ai trouvé que la cause est le manque d'une extension PHP qui n'est plus installée avec l'installation par défaut.
La question qui se pose est : pourquoi dépendre de tous ces outils "prêt-à-porter" et leur pénible configuration ? Une autre solution que je propose est le développement de nos propres outils lorsqu'il s'agit des petits utilitaires ou bien des logiciels que nous n'utilisons qu'une faible partie de leurs fonctionnalités (nous n'utilisons, en général, que 10% des fonctionnalités des logiciels installés sur nos machines). L'idée de ce blog m'est venue en lisant, depuis quelques minutes, une question sur un forum où son auteur se demandait est ce que nous devéloppons nos propres logiciels. La liste des réponses étaient longue : des logiciels de gestion des dépenses, d'autres pour gérer l'emploi du temps des enfants, des outils pour convertir entre différents formats, et plein d'autres outils que les développeurs développent pour eux-même et pour faciliter leurs activités quotidiennes.
A mon avis, avoir un ensemble des outils personnels est une nécessité pour chacun d'entre nous. Avoir le courage de développer les fonctionnalités les plus utilisées dans un logiciel pour ne plus dépendre de ce dernier me semble très justifié quoique la tradition soit de ne plus réinventer la roue. Mais est-ce cette roue est vraiment utile pour moi ? Et si c'est le cas, pourquoi je me trouve obligé de la modifier pour l'agrandir par ci et la réduire par là ?
Durant ma dernière mise à niveau, l'outil que j'étais sûr qu'il fonctionnerait était un simple outil que je développais pour les séances de TP ou j'étais obligé de créer rapidement des classes et des scripts SQL; l'outil me permet de créer les deux en exécutant une seule (mais longue) commande. Pourquoi être sûre ? Parce qu'il s'agit de mon outil, je connais tous ses détails et je peux me retrouver facilement entre les lignes de son code source et de sa documentation. Je n'ai plus besoin de faire des recherches, de poser des questions sur les forums ou bien de contacter son support technique. Et c'est exactement là que réside la puissance des outils personnels.

mercredi 2 mars 2016

Enseigner l’algorithmique pour les débutants .. Deux solutions pour le même problème


Une analyse de la situation actuelle à l’université algérienne peut nous amener à conclure que l’enseigner l’algorithmique est une responsabilité. En effet, les étudiants en 1ère année universitaire n’ont pas encore tranché pour leur future, ils ont, seulement, choisi l’option MI : Mathématiques et Informatique. Ce tronc commun est destiné aux matheux ayant plus de 12 comme note de mathématiques en BAC. Avec l’invisibilité qui règne sur le future de tout jeune algérien, la plus part des étudiants en 1ère année hésitent encore entre suivre un parcours en Mathématiques ou opter pour une carrière en Informatique. L’Algorithmique peut être le module clé pour pousser l’étudiant à l’une des deux possibilités.
Prenons un exemple utilisé généralement pour aider les étudiants à comprendre et à travailler sur les matrices : la deuxième diagonale d’une matrice carrée. Cette diagonale peut être présentée dans différents exercices tels que le carré magique.



En se basant sur l’évolution du cours, nous allons probablement se trouver avec une analyse de passage entre les deux cellules voisines pendant le parcours de cette diagonale :

Ainsi, l’algorithme sera du genre (en prenant “i” comme indice de ligne, “j” comme indice de colonne et N la taille de la matrice) :

i := 1;
j := N;
TQ (i <= N) Faire
     {Notre traitement}
     {La cellule actuelle est accessible par M[i, j]}
     i := i + 1;
     j := j - 1;
FinTQ

Est ce la meilleure solution ? Si on prend le temps d’exécution et l’espace mémoire, la réponse sera Non. Nous pouvons proposer une deuxième solution en partant de l’affirmation suivante (ou de la remarque intuitive, si vous voulez) suivante :
Lorsque i est incrémenté par 1, j est décrémenté par la même valeur”
Une petite adaptation rapide peut, vite, amener l’étudiant à proposer l’algorithme de la forme :

i := 1;
TQ (i <= N) Faire
    {Notre traitement}
    {La cellule actuelle est accessible par M[i, N - i + 1]}
    i := i + 1;
FinTQ

En d’autres termes, le j est écrit en fonction de i et on gagne deux (ou quatre) octets en mémoire centrale.
Pour un développeur, ou même un étudiant en 2ème année, cette solution paraît très simple et même la solution logique, mais pour un étudiante en 1ère année, les choses diffèrent.
Le problème ne réside pas dans la formule de j en fonction de i (le N - i + 1); une fois demandé, les étudiants arrivent souvent à la trouver facilement en partant du fait qu’on parle d’une symétrie par rapport au centre de la matrice :
(i + j) / 2 = (1 + N)/2
i + j = 1 + N
j = N - i + 1
Le vrai problème réside dans cette sensation qui pousse l’étudiant à penser qu’il est possible d’écrire j en fonction de i et de gagner quelques octets en mémoire centrale. Notre enseignant M. B. Chergou (page perso) faisait référence à cela par dire que c’est la partie “génie” dans “ingénieur”, une affirmation encourageante pour des étudiants qui ont déjà choisi “ingénieur en informatique” comme carrière. Cette même affirmation ne peut pas, forcément, avoir le même effet sur des étudiants 1) en licence, 2) n’ont pas encore fait leur choix et 3) se sentent dans l’insécurité.
Pendant une séance de Travaux Dirigés, on peut être amené à présenter l’une des deux solutions; pas seulement pour cet exemple, mais pour dans les différents cas les différents exercices un peu plus compliqué que le calcul de la somme de deux entiers. La solution présentée dépendra, probablement, des éléments les plus actifs pendant cette séance. Elas, un risque se présente : présenter la deuxième solution au problème, sans donner la possibilité aux étudiants, qui n’ont pas eu l’intuition de la détecter, de voir d’autres possibilités va les laisser derrière; répétez la même chose pendant deux à trois séances, et je peux vous garantir que vous aller continuer avec le même groupe qui a fait cette intuition pendant que les autres vont peu à peu abandonner le module en le voyant comme un module intuitive, non méthodique et même poétique (n’oubliant pas qu’il s’agit des matheux).
A mon avis, il est très important d’opter pour la première solution; la solution méthodique, sans ajouter les contraintes d’optimisation sur les étudiants et de présenter la deuxième solution par la suite comme un raccourcis qui peut être emprunté (ou pas). Ainsi, l’aspect “exacte” de l’algorithmique et de la programmation de manière générale restera préservé et les étudiants seront (pour le moment) protégés d’avoir l’impression que la programmation est basée des capacités d’observation particulières ou nécessite une intelligence spéciale.

P.S : Cet article est fait suite à un constat réel qui dépend (comme les sciences sociales le précisent) de l’échantillon des étudiants, la succession des évènements et le contenu du cours et des travaux dirigés présentés. Un tel problème ne sera pas, probablement, rencontré si les étudiants ont déjà fait des travaux de programmation (tous les étudiants) (Cours CS 106 - U. Stanford)