Proj-2014-2015-SmartClassRoom

From air
Jump to: navigation, search

Contents

Présentation

Ce projet est un projet de fin d'étude, qui se déroule à Polytech Grenoble, et soutenu par la Fabmstic. L'objectif à long terme de ce projet est de mettre en place des technologies qui permettent d'améliorer les techniques d'enseignement dans les salles de cours. On peut ainsi imaginer des activités pédagogiques interactives comme des évaluations fournissant des réponses instantanées et permettant ainsi aux enseignants de voir quand un concept doit être révisé ou quand ils doivent davantage aider les élèves. Ce projet est donc principalement destiné aux enseignants. Il leur permettra de passer d'un type d'enseignement à un autre plus évolué, c'est à dire gérer plus efficacement leurs classes, et évaluer la compréhension des élèves durant le cours. On distingue ensuite les élèves qui pourront entre autres organiser leurs propres fichiers multimédias, prendre des notes, collaborer avec d'autres élèves ou partager des fichiers avec les enseignants. Ce projet se divise en deux grandes parties  :

  • Tableau interactif
  • Tiled Display sur les tables tactiles

Equipe

  • Superviseurs: Didier DONSEZ
  • Intervenants extérieurs : Jérôme MAISONNASSE et Amr AL-YAFI.
  • Etudiants RICM5: Radhouane BEN YOUNES, El Hadji Malick FALL, Benoît PERRUCHE, Adam TIAMIOU
  • Etudiants DUT R&T 1ère année: Quentin FOMBARON et Lucas REYGROBELLET

Documents liés

  • Le SRS (Software Requirements Specification) est accessible ici
  • Github repository : [1] (Pour des raisons de confidentialité, une seule partie du code (celle du Tiled Display) est accessible)
  • Diagrammes UML : [2]

Objectifs

Tableau interactif

Pour cette partie, nous sommes partis d’un projet déjà développé par des étudiants de l’ENSIMAG : le mur digital interactif. Le but de ce projet était d'ajouter des fonctionnalités électroniques à un tableau blanc ordinaire. L'utilisateur travaille sur le tableau, écrivant ou dessinant avec des feutres classiques. L'idée était de de permettre à l'utilisateur de prendre des copies numériques des éléments du tableau, et de lui renvoyer cette copie à la place de l'élément original. Celui-ci peut ensuite être effacé du tableau et l'utilisateur interagit alors uniquement avec la version numérique. Il peut ainsi faire toutes sortes de manipulations comme dupliquer l'objet, le déplacer, l'élargir, le réduire…

Nous devions apporter des améliorations à cette implémentation déjà fonctionnelle. Pour cela nous devions rajouter les fonctionnalités suivantes :

  • Projection de la traduction du texte écrit au tableau suivant la langue choisie
  • Résolution automatique d’une équation et tracé de courbe de la fonction

Tiled display avec les tables

Les tables fournies par Digitale dont nous disposons possèdent une sur-couche linux SPHER OS dont nous devrons nous débarrasser afin de créer notre propre interface.

Dans le but d’effectuer un Tiled display sur les quatre tables, nous avons imaginer créer un serveur depuis l’une des tables. Chacun des écrans afficherait ensuite une page web représentant une partie de l’image globale.

Nous avons tout d’abord lister les différents déplacements possibles d’entités, ainsi que les moyens de communications entre les tables. Nous avons ensuite diviser le travail en trois parties : une portant sur le codage du moteur physique qui devra nous permettre de réaliser nos interactions, une autre sur la création du serveur et de la page web globale, et une dernier tournée vers la communication entre les tables à l’aide de sockets web ou par un bus de diffusion.

Suite à notre recherche sur les différents logiciels existants pour faire du tiling display, nous sommes tombé sur Sage2, un html viewer utilisé pour afficher de nombreux éléments dans de multiples fenêtres. Basé sur node.js, nous rencontrons des problèmes lors de l’installation de npm.

Le problème rencontré est le même sous windows ou linux.

Les objectifs d’interactions à réaliser dans notre interface sont les suivants:

  • pouvoir déplacer les fenêtres
  • zoomer / dezoomer sur plusieurs tables
  • afficher un contenu statique, puis le répliquer dans les différentes fenêtres
  • une touche pour un affichage plein écran (sur toutes les tables)
  • la possibilité de faire tourner une fenêtre sur elle-même (ou rotation 90° à chaque coup)
  • réaliser des applications en commun (par exemple un cours d’anatomie)
  • proposer une représentation spatiale des tables afin de prévoir à l’avance les zones affichables
  • prévoir les distances d’écartements entre les tables (prévoir les bordures)

Architecture Générale

L'architecture générale peut être décrite comme-suit :

ArchiGeneral.png

Les deux entités du projet communiquent via des sockets de connexion.

Tiled Display

Chaque client affiche une page web (interface) délivrée par un serveur Express (NodeJS) connecté à un port précis.

La communication entre les clients et le serveur se fait grâce au module NowJS : https://github.com/Flotype/now/ qui est basé sur des socket.io :

  • Les clients et le serveur vont partager un composant Now qui peut contenir des méthodes ou des variables.
  • Les méthodes sont implémentées dans ce composant, côté client et côté serveur.
  • Lorsqu'un client veut appeler la méthode d'un ou plusieurs ou tous les clients (lui compris ou non), il appelle une méthode de now implémentée côté serveur, et c'est ce dernier qui est chargé d'appeler le ou les méthodes des clients.
  • NowJs fonctionne sur le principe de groupe. Le premier groupe nommé "everyone" contient tous les clients. On peut ensuite créer des sous-groupes et y ajouter les clients au fur et à mesure. Cela rend facile la sélection des clients pour l'appel de méthode.

Tableau interactif

En résumé, après la capture de l'image d'entrée, suite à une action au niveau de l'interface, le Backend Java amorce la détection du texte. Différents traitements sont ensuite appliquées puis les scripts batch correspondants sont exécutés avec les paramètres requis. Ceux là contiennent les différents appels aux scripts Python associés et/ou à bibliothèque de transformation en image. Si une erreur survient, une exception est levée. Sinon on obtient bien une image de sortie (qui peut être erronée si le résultat de la détection n'est pas correct par exemple).

Prérequis - Projet Table Tactile

  • Le serveur peut accueillir au maximum quatre clients
  • Les tables doivent être disposées en carré et orientées vers l'extérieur, de sorte que l'on puisse tourner autour du carré et être dans le bon sens de lecture
  • Le serveur distingue quatre orientations : Nord-Ouest, Nord-Est, Sud-Ouest, Sud-Est.
  • A chaque fois qu'un client se connecte, le serveur lui attribue la première orientation disponible suivant l'ordre ci-dessus.
  • Utiliser Google Chrome de préférence
  • Activer les événements tactiles pour le navigateur Google Chrome (chrome://flags/#touch-events)
  • Pour chaque table, le mode plein écran doit être lancé manuellement (F11) pour le mode Tiled Display (sinon la taille maximale du média sera celle du Body)
  • Pour lancer une vidéo, utiliser les fichiers .mp4 (chrome uniquement), .ogg, .webm

Implémentation des fonctionnalités

Partie Tableau interactif

Mise en place d'un OCR

Objectif :

L'objectif est d'être capable de récupérer du texte à partir d'une image donnée en entrée. Ce texte est destiné à être sauvegardé dans un fichier qui sera exploité par les prochains modules.

Technologies utilisées :

Tess4J : http://sourceforge.net/projects/tess4j/

C'est un wrapper Java JNA pour l'API de Tesseract. Tess4J est distribué sous la licence Apache, v2.0. Tesseract est un moteur open source de reconnaissance optique de caractères qui peut être utilisé :

  • soit directement, en ligne de commandes soit par l'intermédiaire d'une interface graphique pour reconnaitre du texte avec mise en page basique ; cet usage est déjà fonctionnel.
  • soit avec des surcouches gérant les mises en page complexes, etc., comme ocropus (encore en version beta).

Conception :

Afin de faire de la récupération de texte sur des images, nous avons choisi d'utiliser Tess4J. Ce choix a été fait par recommandation et par analyse comparative. Nous avons tout d'abord contacter Mr Laurent BESACIER qui nous a recommandé Tesseract. Puis nous avons fait un benchmark des différents OCR Open Source. Le choix de l'OCR est très important pour le procédé de traduction que nous comptons mettre en place.

Nous avons successivement testé Tesseract, GOCR, javaocr-source, Asprise OCR (qui détecte même des codes barres et QR Codes). Tesseract et Asprise OCR sont ressortis comme les plus concluants pour la détection mais malheureusement le second n'est pas Open Source. Toutefois comme le code développé par les étudiants de l'ENSIMAG était en JAVA, plutôt que de faire un appel système, nous avons sauté sur l'occasion d'utiliser Tess4J qui était une implémentation de Tesseract en Java. En effet il a été très facile de l'intégrer dans le code existant et de le lier aux différentes fonctions déjà présentes. Il s'agissait juste d'insérer un nouveau package.

Problèmes rencontrés:

L'intégration de Tess4J au projet existant a été plutôt simple. Toutefois cette librairie est seulement utilisable sur Windows et pas sur Linux à cause des DLL. Le problème rencontré était plutôt liée aux performances de l'OCR lui-même. Il faut respecter une certaine syntaxe pour avoir une détection idéale. Certains caractères ne sont pas en effet reconnus ou confondus. Par exemple si un 'r' est trop proche d'un 'v' il peut être interpréter comme un 'n'. Le temps de détection n'est pas optimal. Cela se ressent quand le texte est trop long.

Intégration d'un module de traduction à l'OCR

Objectif :

L'objectif est de traduire le texte récupéré par Tesseract et de le convertir en image de sortie qui sera affiché à l'utilisateur sur le tableau.

Technologies utilisées :

Python Goslate: http://pythonhosted.org/goslate/

C'est une API gratuite en python qui fournit un service de traduction de Google en interrogeant le service de Google Traduction.

Conception :

Pour mettre en place la traduction, nous commençons tout d'abord par récupérer le String renvoyé par Tess4J dans un fichier intitulé entree.txt. Le script que nous avons implémenté en python effectue tout d'abord une lecture de ce fichier dans son ensemble (et non pas mot par mot sinon nous n'obtiendrons pas une traduction fidèle). La traduction est ensuite renvoyée dans un fichier de sortie sortie.txt. Grâce à Image Magick, ce fichier de sortie est convertie en image PNG qui va être projetée sur le tableau par le vidéo-projecteur. Pour plus de facilité, nous avons limité le choix des langues à cinq : français ('fr'), anglais ('en'), espagnol ('es') , italien ('it') et allemand ('de').

Problèmes rencontrés:

Le premier problème rencontrée est que Tess4J détecte plus facilement les caractères en majuscule. Cependant, ces derniers ne sont pas très adaptés pour une traduction. De ce fait, au niveau du Java, lorsque nous récupérons le String résultat nous le transformons en minuscule grâce à la méthode toLowerCase(). A ce String nous appliquons au préalable un traitement de « nettoyage » avec la méthode trim() qui permet d'éliminer les éventuels caractères spéciaux qui se rajoutent et qui sont invisibles à l’œil nu. Il est nécessaire d'avoir une bonne connexion pour accélérer le processus de traduction.

Le passage du paramètre de la langue de traduction du code Java au script Python était plutôt délicat.

Intégration à l'OCR d'un module de résolution d'équations et de calculs élémentaires

Objectif :

L'objectif est que l'utilisateur écrive au tableau soit une opération élémentaire (addition, soustraction, multiplication et division), soit une équation du type ax+b et obtienne soit le résultat, soit la courbe de la fonction, par affichage.

Technologies utilisées :

Librairies de Python :

Microsoft Visual Studio 2008 : http://download.microsoft.com/download/A/5/4/A54BADB6-9C3F-478D-8657-93B3FC9FE62D/vcsetup.exe

Conceptions:

Pour intégrer le module de résolution d'équation, nous reprenons le même modèle que pour la traduction (fichier entrée/fichier sortie) mais avec quelques particularités. Nous avons conçu trois options pour les équations qui sont associés aux trois méthodes que nous avons implémentées pour elles :

  • L'option -r :

Elle est associée à la méthode solve_linear_equation(equ). Cette méthode prend en paramètre une équation du type ax+b et retourne la valeur de x , Pour la résolution on considère implicitement ax+b=0. Nous avons défini une expression régulière (r"(\d*)[xX]\+(\d+)") qui nous permet avec la méthode group() de récupérer les coefficients a et b et de résoudre l'équation. Le résultat de X avec 3 chiffres après la virgule est écrit dans le fichier de sortie puis affiché.

  • L'option -rs :

Elle est associée à la méthode solve_linear_equation_with_result(equ). Elle reprend la même idée que l'option précédente sauf que dans ce cas précis, on a un élément en plus qui correspond au résultat. On a ainsi des équations du type ax+b=c. L'expression régulière appliquée devient ainsi r"(\d*)[xX]\+(\d+)=(\d+)".

  • L'option -p :

Elle correspond à la méthode plot_equation(formula, x_range) et prend en entrée une formule du type ax+b et un intervalle d'affichage que nous avons fixé par défaut à [-10,11]. Elle permet l'affichage de la courbe de la fonction. Cette méthode n'implique pas l'édition d'un fichier de sortie. La courbe de la fonction est directement enregistré dans un fichier png. Toutes ces opérations (tracé, enregistrement) sont possibles grâce à des méthodes inhérentes aux librairies Matplotlib et Numpy (eval, plot, savefig).

Pour toutes ces options le format des équations doit être scrupuleusement respecté : pas d'espace, pas de nombres décimaux, pas de nombres négatifs. Il convient aussi de choisir la bonne équation pour le bon format d'entrée.

  • L'option -o :

Elle fait appel à la méthode solve_operation(formula). Celle-ci permet d'effectuer les opérations élémentaires : addition, soustraction, multiplication et division entre deux nombres. Ce format d'entrée est spécifié par l'expression régulière r"(\d*)[xX]\+(\d+)".

Problèmes rencontrés :

Le problème majeur était lié à l'installation de la librairie Numpy sur Windows qui s'est avérée plus compliquée que prévue. Pour se faire nous avons dû installer Microsoft Visual Studio 2008 pour pouvoir répondre à toutes les exigences de compilation pour intégrer cette bibliothèque à Python 2.7.

Dans une moindre mesure, concernant les options -r et -rs il fallait prendre en compte le cas où x=1 dans l'expression ax+b. Nous avons juste rajouté la condition selon laquelle si le premier caractère renvoyé par la méthode group() valait "" (c’est-à-dire vide) , le nombre associé est 1.

Ce problème est réapparu dans l'option -p. Pour faire appel à la méthode eval() le format de la formule ne doit plus être ax+b mais a*x+b. La transformation est plutôt facile au niveau du Java grâce à la fonction replace("x", "*x") mais elle ne doit se faire dans le cas où on a affaire à une équation du type x+b ("x\\+(\\d+)") pour éviter les erreurs (la formule x+1 devient *x+1 et n'est plus interprétée correctement).

Partie Tiled Display

Lecture d’une vidéo (pdf, images etc...) en Tiled Display

Objectif :

Afficher une video sur plusieurs tables tactiles, sans qu'il y est de latence entre les écrans.

Technologies utilisées :

Module NowJS : https://github.com/Flotype/now/

Ce module utilise les socket.io et permet de créer des applications web fonctionnant en temps-réel. Fonctionnement : Un composant “now” est partagé entre le serveur et tous les clients. On peut ainsi lancer une fonction implémentée sur le serveur à partir d’un client, et aussi avoir accès à tous les composants déposés dans “now”.

Module node-demux : https://github.com/tmarrinan/node-demux

Ce module permet de décoder en temps-réel une video en images brutes. Il utilise la technologie ffmpeg.

Module fluent-ffmpeg : https://github.com/fluent-ffmpeg/node-fluent-ffmpeg

Ce module très puissant permet d’utiliser la technologie ffmpeg sur NodeJS. Contrairement à node-demux, il permet de décoder des videos en temps-réel et en plusieurs formats, comme .flv, en incluant les son. Il permet aussi de décoder uniquement la partie audio d’un fichier vidéo. Ce module est très efficace pour faire du streaming vidéo.

Problèmes rencontrés:

Nous avons estimé que le module fluent-ffmpeg serait suffisant pour que chaque client reçoivent les données vidéos en temps-réel. Ce module est capable de décoder la video en format .flv et de piper les données dans un tuyau (stream) lu en sortie par un lecteur flowplayer. En gros, le client lance une méthode “get”, le serveur pipe les données dans la variable “res” qui est le résultat du “get”. Ensuite, côté client le lecteur flowplayer lit les données qui sont délivrées en continu.

Le problème est que le format .flv est non open-source et le lecteur Flowplayer ne permet pas d’utiliser les données une fois interprété. Par exemple, il nous était impossible de capturer chaque images du lecteur et des les copier dans un nouveau canvas; l’idée étant de pouvoir redimensionner les images à notre guise.

Conception :

Afin que chaque client puisse recevoir en temps-réel les données de la vidéo et puisse les traiter pour faire du Tiled Display, nous avons décidé d'utiliser :

  • le module node-demux pour délivrer les images, ou la capture en temps-réel d'une vidéo HTML5 dans un canvas toutes les 1000/n millisecondes (n = 60, 30 ... fps)
  • le module fluent-ffmpeg pour délivrer la partie audio

Les images délivrées sont traitées et redimensionnées par le client (cf: afficher une partie de la vidéo) et copiées dans un “canvas” spécifique.

Concernant la partie audio, chaque client possède un lecteur Flowplayer non visible et connecté par un tuyau au Serveur. Le module fluent-ffmpeg va ainsi permettre de délivrer toute sorte de données audio dans chaque tuyau de chaque client. A noter que ce module peut délivrer la partie audio d’un fichier vidéo à partir d’un temps précis (par exemple à partir de la dixième minute); permettant ainsi de synchroniser les données lorsqu’un utilisateur avance ou recule la vidéo.

Envoi d’une fenêtre vers une autre table, Rotation, Resize

Objectif :

Permettre à l'utilisateur d'envoyer par drag & drop un objet (video, pdf, image...) sur une autre table accolée à la sienne.

Technologies utilisées :

jquery.pep.js : http://pep.briangonzalez.org/ https://github.com/briangonzalez/jquery.pep.js Ce module permet de faire du Drag and Drop sur des objets HTML. Il permet de calculer la vélocité du geste à tout moment et notamment lorsque l’utilisateur lâche l’objet.

ATTENTION: Nous avons effectué des modifications dans ce module pour définir nous-même les limites de déplacement des objets. Les modifications commencent à l'endroit (LIGNE 866 -> 912) où est indiqué le commentaire : /*AJOUT FONCTIONNALITE SUPPLEMENTAIRE*/

Nous avons aussi ajouté d'autres options.

interact.js : http://interactjs.io/ https://github.com/taye/interact.js Ce module permet d'appliquer une rotation sur un objet et de changer ses dimensions.

jester.js : https://github.com/plainview/Jester Ce module permet d'utiliser les évènements "doubletap"

Problèmes rencontrés:

Il a tout d'abord fallu adapter notre moteur physique à la sensibilité tactile des tables. Nous avons aussi dû préférer chrome à mozilla car firefox ne permettait pas de manipulation tactile performante.

Conception :

Dans un premier temps, à chaque fois qu'un client crée une fenêtre, il prévient tous les autres clients qui vont aussi la créer et la cacher. Dès qu'un client bouge une fenêtre, il envoie les coordonnées du mouvements aux autres clients. Ces derniers vont ensuite calculer ces coordonnées par rapport à l'orientation de la table (Nord-Est, Nord-Sud etc...). Par exemple, si l'utilisateur envoie la fenêtre à droite en dehors du cadre, la table tactile à droite affichera la fenêtre. Si il n'y a pas de table tactique à une orientation, alors la fenêtre ne peut sortir du cadre, il y a un mur.

A chaque fois que l'utilisateur fait un "doubletap" sur le header de la fenêtre, il se repositionne à son état angulaire d'origine, c'est-à-dire, comme si il n'y avait jamais eu de rotation.

Jeux ping-pong et drawing

Objectif :

L'objectif est de réaliser une application multiutilisateur avec une gestion de l'affichage en tiled display si besoin.

Jeux Ping-pong : Application se jouant à deux, sur deux tables tactiles en face à face, et chaque table affiche la moitié du terrain de jeux.

Application Drawing : Les utilisateurs se partage une zone de dessin à la manière d'un Google Doc.

Technologies utilisées :

Ping Pong Game : http://cssdeck.com/labs/ping-pong-game-tutorial-with-html5-canvas-and-sounds Nous nous sommes inspirés de ce jeu en effectuant le minimum de changement possible pour le rendre multijoueur en Tiled Display

Problèmes rencontrés:

Adaptation de la sensibilité et gestion des bordures.

Conception :

Ping-pong : Changement effectués :

  • Chaque client ne bouge qu'une seule barre (celle du bas) et envoie les coordonnées du mouvements à l'autre client. En d'autre termes, la barre du haut pour chaque client est bougé par l'autre client.
  • Le client à avoir lancé le jeu est le maître, il calcule les interactions entre les objets (balle, barre, mur...) et envoie les événements à l'autre client.
  • Etant donné que chaque client bouge la barre du bas, il faut que le client non maître bouge la balle dans la direction et sens opposé à ceux du clients maître.
  • Découpage de la canvas pour n'afficher que la moitié inférieure du terrain
  • Ajout d'un bouton QUIT


Drawing : Chaque client effectuant un tracé envoie les coordonnées et la couleur du tracé à tous les autres clients.

Gestion de projet

Management et leadership

Nous avons décidé, malgré la séparation du projet en deux sous parties (et donc notre division en deux groupes de deux personnes), de travailler ensemble au même endroit tous les jours ouvrables de la semaine. Cela avait pour but de nous permettre à tout instant de connaître l’état d’avancement des deux projets. Les caractéristiques de chacun étaient ainsi bien exploitées. La communication interpersonnelle se faisait donc en continu (utilisation de réseaux sociaux les week-ends), afin que nul ne reste bloqué trop longtemps sur un problème. Issus de milieux très différents, la présence d’un arbitre a parfois été nécessaire. Le moindre conflit était immédiatement contrôlé par la présence d’une troisième personne prenant le rôle d’arbitre (les rôles ont tournés au cours du projet). Ces conflits étaient souvent dûs à la trop longue durée de côtoiement, côtoiement qui paradoxalement nous permettait aussi de progresser bien plus vite pour la réalisation des tâches.

Afin d'être le plus productif possible nous nous sommes séparés en deux groupes selon le sujet sur lequel chacun souhaitait travailler. De plus, nous avons organisé certaines activités hors travail (repas, bowling) afin de renforcer les liens ainsi que le respect mutuel.

Les premières semaines ont été marquées par la présence de nombreux brainstormings, afin de cibler et séparer intelligemment les taches. Par la suite, ces séances se sont plus espacées et étaient propres à chaque partie du projet.

Un autre aspect management de notre projet était la gestion des deux étudiants de DUT. Afin de les motiver au maximum, nous leur avons laissé le choix du projet. Nous organisions ensuite des réunions hebdomadaires en fonction de leurs disponibilités. Les tâches qui leur étaient proposées devaient permettre des résultats visibles assez rapides (toujours dans le but de les motiver).


Notre groupe a la particularité d’être scindée en deux. De ce fait un leadership globale ne peut pas être mis en place. On a donc plutôt affaire à un management participatif qui implique que chaque membre va détailler le travail réalisé à son binôme. En d’autres termes, le second membre est chargé de superviser et d’apporter sa vision et son jugement sur le travail de son collègue. Par la suite, ils vont présenter à intervalles moins réguliers l’état d’avancement des objectifs principaux (sprint) à l’autre binôme. L’objectif était qu’un groupe pouvait solliciter temporairement l’aide d’un membre de l’autre groupe, pour effectuer une tâche complexe.

A chaque objectif principal à réaliser, nous avons décidé de définir des sous objectifs pour chaque membre en restreignant les interdépendances. Cela a permis d’éviter les conflits au maximum. Pour résoudre les conflits, nous avons sollicité un intervenant extérieur qui était au courant de l’avancement détaillé de notre projet.

Diagramme de Gantt

GanttDiagram.png

Gestion des risques

Notre projet étant pour l’instant à but non lucratif, il est soumis principalement à des risques techniques, matériels et de délais. Pour les identifier nous avons défini la matrice des risques ci-dessous :

MatriceRisques.png

Récapitulatif

Ce projet de fin d’étude, qui s’est étalé sur deux mois, est le plus gros projet que nous avons eu à réaliser durant notre cursus à Polytech. Ces deux mois nous ont donc poussé à nous poser de nouvelles questions sur la gestion d’un groupe de personnes travaillant sur un même sujet mais avec deux directions différentes. Le groupe était composé de quatre étudiants RICM5 ainsi que de deux DUTs. Le cours de Management pour l'innovation nous a permis de découvrir de nouvelles techniques qui nous ont permis de gérer ces deux situations. Il nous a permis d’approfondir et de mettre en pratique des notions que nous avons abordées lors des années précédentes.

Nous avons suivi le cahier des charges et effectué l’ensemble des tâches à réaliser grâce à une bonne motivation, une entraide journalière et une répartition intelligente et concertée des tâches. Nous avons aussi pu éviter les conflits en évitant qu’ils s’enveniment et en promulguant de multiples activités hors travail. D’un point de vue personnel, ce projet nous a tous permis d’élargir nos compétences et de découvrir de nouvelles technologies et procédés.