# Vémock

## <a name="_Toc77866761"></a><span style="color: rgb(0, 0, 0);"><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;"><span style="font: 7.0pt 'Times New Roman';"> </span>I.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Introduction</span>

### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866762" style="color: rgb(0, 0, 0);"></a><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;">1.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Contexte</span>

<span style="color: rgb(0, 0, 0);">Ce projet annuel se repose énormément sur le comportement des stations, car ce sont elles qui vont recharger les vélos et indique à l'utilisateur ou en prendra.</span>

<span style="color: rgb(0, 0, 0);">Puisque la mairie de Paris n'a pas souhaité nous financez pour mettre à disposition des stations dans la ville, il a fallu les simuler nous-mêmes pour avoir un comportement cohérent sur le site.</span>

### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866763" style="color: rgb(0, 0, 0);"></a><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;">2.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Application choisie</span>

<span style="color: rgb(0, 0, 0);">Nous avons développé Vemock pour répondre à ce besoin et simuler le comportement d'une station complètement autonome.</span>

<span style="color: rgb(0, 0, 0);">Cette application enverra régulièrement au serveur l'évolution d'une station autonome, à savoir le nombre d'emplacements vélos utilisés, le niveau de batterie, la puissance de charge, etc.</span>

## <span style="color: rgb(0, 0, 0);"><a name="_Toc77866764" style="color: rgb(0, 0, 0);"></a><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;"><span style="font: 7.0pt 'Times New Roman';"><span style="mso-spacerun: yes;"> </span></span>II.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Focus sur l’application</span>

### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866765" style="color: rgb(0, 0, 0);"></a><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;">1.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>État d’une station et configuration</span>

<span style="color: rgb(0, 0, 0);">Il y aura plusieurs paramètres à simuler dans le cycle de vie d'une borne, à savoir :</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>La batterie</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Si la station est active</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>La puissance de charge</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Le nombre d'emplacements de vélo utilisé</span>

<span style="color: rgb(0, 0, 0);">Ces paramètres doivent suivre une évolution cohérente donc certaines règles ont été mises en place afin d'apporter de la cohérence.</span>

#### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866766" style="color: rgb(0, 0, 0);"></a>Comportement de la batterie</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Elle doit varier dans un intervalle de 0 à 100%</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Elle se décharge constamment, mais un peu moins la nuit.</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Elle dépend de la puissance de charge de la borne et un petit peu d'aléatoire</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Elle se décharge beaucoup plus vite s'il y a beaucoup de vélos sur la borne</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Si la batterie est en dessous de 15 pour 100, elle se rechargera plus facilement</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Dans le cas où la batterie tombe en dessous de 15 pour 100 et si la configuration le permet, la station passera en statut inactif</span>

#### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866767" style="color: rgb(0, 0, 0);"></a>Puissance de charge</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Elle dépend d'un peu d'aléatoire</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>La puissance de charge est faible le matin, très élevé en journée, puis à nouveau faible le soir.</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>La puissance de charge est nulle la nuit</span>

#### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866768" style="color: rgb(0, 0, 0);"></a>Nombre d’emplacements utilisés</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Le nombre d'emplacements utilisé est un peu aléatoire</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>L'évolution du nombre d'emplacements utilisés doit être cohérentes par rapport au précédent état.</span>

#### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866769" style="color: rgb(0, 0, 0);"></a>Configuration d’une station</span>

<span style="color: rgb(0, 0, 0);">Au démarrage, l'application va charger la configuration propre à la borne qu'elle doit simuler, à savoir :</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>L'idée de la station</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Si elle a le droit de passer en statut inactif quand la batterie est trop basse</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Le nombre maximum d'emplacements vélo</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Le nom du fichier d'historique pour la reprise</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Le temps d'attente entre chaque envoi de données</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>La puissance maximale de charge</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Le token d'authentification auprès du serveur</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Le lien pour accéder au serveur</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Si elle doit afficher des données de débogage pendant son exécution</span>

<span style="color: rgb(0, 0, 0);">Si ces données sont mises à jour et que la station redémarre, elle prendra en compte les changements.</span>

### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866770" style="color: rgb(0, 0, 0);"></a><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;">2.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Persistance de l’état et reprise</span>

<span style="color: rgb(0, 0, 0);">Si jamais une station s’éteint (l'application est coupée), elle ne doit pas repartir avec des valeurs initiales lorsqu'elle redémarre, mais bien avec les dernières données générées.</span>

<span style="color: rgb(0, 0, 0);">C'est pour cela qu’à chaque nouveau changement de statut de la borne, un fichier historique est mis à jour pour garder en mémoire le dernier statut connu de la borne.</span>

<span style="color: rgb(0, 0, 0);">Au démarrage de l'application, si ce fichier n'existe pas, alors l'application prend des valeurs initiales par défaut, sinon elle reprend là où elle s'était arrêtée.</span><span style="color: rgb(0, 0, 0);">**<span style="font-size: 14.0pt; mso-bidi-font-size: 11.0pt; line-height: 110%; mso-fareast-font-family: HGMinchoE; mso-fareast-theme-font: major-fareast; mso-bidi-font-family: 'Times New Roman'; mso-bidi-theme-font: major-bidi; text-transform: uppercase;"> </span>**</span>

### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866771" style="color: rgb(0, 0, 0);"></a><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;">3.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Envoie des données</span>

<span style="color: rgb(0, 0, 0);">À chaque nouveau changement d’état, une métrique est envoyée sur le serveur API.</span>

<span style="color: rgb(0, 0, 0);"><span style="mso-spacerun: yes;"> </span>Cette requête contient :</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Le token d'autorisation de la borne dans l’en-tête qui permettrait au serveur d'identifier celle-ci</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Le pourcentage de batterie</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>La puissance de charge</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Si elle est active</span>

<span style="color: rgb(0, 0, 0);"><span style="font-family: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol;"><span style="mso-list: Ignore;">·<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Le nombre d'emplacements vélo utilisé</span>

<span style="color: rgb(0, 0, 0);">Nous utilisons le client HTTP standard fourni par la lib python.</span>

<span style="color: rgb(0, 0, 0);">[![Image1.png](https://wiki.nospy.fr/uploads/images/gallery/2022-09/scaled-1680-/5vHimage1.png)](https://wiki.nospy.fr/uploads/images/gallery/2022-09/5vHimage1.png)</span>

<span style="color: rgb(0, 0, 0);"> </span>

### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866772" style="color: rgb(0, 0, 0);"></a><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;">4.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Logging des actions</span>

<span style="color: rgb(0, 0, 0);">Si les logs sont activés ; à chaque changement d'état de la station ; il sera affiché en compte sol le nouvel état de la station ainsi que la requête envoyée.</span>

<span style="color: rgb(0, 0, 0);">Ces données sont également sauvegardées dans un fichier.</span><span style="color: rgb(0, 0, 0);"><span style="mso-no-proof: yes;"> </span><a name="_Toc77773383" style="color: rgb(0, 0, 0);"></a></span>

<span style="color: rgb(0, 0, 0);">[![Image2.png](https://wiki.nospy.fr/uploads/images/gallery/2022-09/scaled-1680-/xuvimage2.png)](https://wiki.nospy.fr/uploads/images/gallery/2022-09/xuvimage2.png)</span>

### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866773" style="color: rgb(0, 0, 0);"></a><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;">5.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Générateur du docker-compose</span>

<span style="color: rgb(0, 0, 0);">Pour simuler le comportement de 100 stations, le fichier docker compose **docker-compose.yml** fais plus de 2400 lignes. Bien sûr, il serait trop long d'écrire toutes ces lignes à la main…</span>

<span style="color: rgb(0, 0, 0);">Nous avons donc mis au point un script python qui permet à partir d'un fichier de configuration JSON beaucoup moins gros de générer notre **docker-compose.yml** final.</span>

<span style="color: rgb(0, 0, 0);">Voici un exemple des fichiers de configuration avec seulement 2 stations :</span>

<span style="color: rgb(0, 0, 0);"> [![Image3.png](https://wiki.nospy.fr/uploads/images/gallery/2022-09/scaled-1680-/TQgimage3.png)](https://wiki.nospy.fr/uploads/images/gallery/2022-09/TQgimage3.png)</span>

<span style="color: rgb(0, 0, 0);">[![Image4.png](https://wiki.nospy.fr/uploads/images/gallery/2022-09/scaled-1680-/y7Nimage4.png)](https://wiki.nospy.fr/uploads/images/gallery/2022-09/y7Nimage4.png)</span>

## <span style="color: rgb(0, 0, 0);"><a name="_Toc77866774" style="color: rgb(0, 0, 0);"></a><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;">III.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Choix d’implémentations<a name="_XML_Parser" style="color: rgb(0, 0, 0);"></a></span>

### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866775" style="color: rgb(0, 0, 0);"></a><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;">1.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Langage choisi</span>

<table border="1" id="bkmrk-pour-ce-projet%2C-nous" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 73.1359%;"></col><col style="width: 26.963%;"></col></colgroup><tbody><tr><td style="vertical-align: middle; text-align: justify;"><span style="color: rgb(0, 0, 0);">Pour ce projet, nous avons choisi d'utiliser le langage python, car c'est selon nous celui qui répondait le mieux à notre besoin. Il possède beaucoup de librairies permettant de parser et traiter des données, ce qui nous a permis d'aller relativement vite.</span></td><td style="vertical-align: middle;">[![Image5.jpg](https://wiki.nospy.fr/uploads/images/gallery/2022-09/scaled-1680-/image5.jpg)](https://wiki.nospy.fr/uploads/images/gallery/2022-09/image5.jpg)</td></tr></tbody></table>

### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866776" style="color: rgb(0, 0, 0);"></a><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;">2.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Contrainte de performance</span>

<span style="color: rgb(0, 0, 0);">Puisque cette application est destinée à tourner en plusieurs exemplaires sur un Raspberry, il faut que celui-ci soit le moins gourmand possible.</span>

<span style="color: rgb(0, 0, 0);">C'est pourquoi nous n'utilisons pas de librairies externes, mis à part **dotenv** dans l’environnement de développement.</span>

<span style="color: rgb(0, 0, 0);">Avec toutes les optimisations faites, l'application ne prend pas plus de 10 Mo de mémoire vive pendant son exécution.</span>

## <span style="color: rgb(0, 0, 0);"><a name="_Toc77866777" style="color: rgb(0, 0, 0);"></a><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;">IV.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Bilan du projet</span>

### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866778" style="color: rgb(0, 0, 0);"></a><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;">1.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Problèmes rencontrés</span>

#### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866779" style="color: rgb(0, 0, 0);"></a>Librairie Requests trop lourde</span>

<span style="color: rgb(0, 0, 0);">Au tout début, nous n’utilisions pas le client natif python, mais une librairie se nomment **Requests**.</span>

<span style="color: rgb(0, 0, 0);">Lors de l'exécution de l'application, nous constations que celle-ci prenait énormément de mémoire. Après beaucoup de vérifications, nous avons découvert que cela venait de cette librairie lorsqu'elle était importée.</span>

<span style="color: rgb(0, 0, 0);">Nous avons donc dû faire un changement pour utiliser plutôt la librairie native de python, qui est un peu plus verbeuse, mais moins consommatrice.</span>

#### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866780" style="color: rgb(0, 0, 0);"></a>Équilibrage des métriques</span>

<span style="color: rgb(0, 0, 0);">L'algorithme définissant l'état de la station n'a pas été parfait du premier coup et nous faisions face à des données qui n'étaient pas cohérentes (batterie toujours à 100%, ne charge nulle, capacité de vélo dépassé …).</span>

<span style="color: rgb(0, 0, 0);">L’application a ainsi subi plusieurs évolutions pour que le comportement soit le plus cohérent possible.</span>

#### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866781" style="color: rgb(0, 0, 0);"></a>Fuites de mémoires sur la durée</span>

<span style="color: rgb(0, 0, 0);">En plus de la librairie **Requests** que nous avons enlevé, nous constations des fuites de mémoire lors de l'exécution prolongée de l'application.</span>

<span style="color: rgb(0, 0, 0);">Cela venait du fait qu'à chaque requête où log, l'application gardé en cache certaines données et ne les libérait pas tout de suite.</span>

<span style="color: rgb(0, 0, 0);">Afin de garder une consommation de mémoire stable, nous manipulons manuellement le **Garbage Collector** de python pour le forcer à se vider à chaque changement d'état.</span>

### <span style="color: rgb(0, 0, 0);"><a name="_Toc77866782" style="color: rgb(0, 0, 0);"></a><span style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman';"><span style="mso-list: Ignore;">2.<span style="font: 7.0pt 'Times New Roman';"> </span></span></span>Conclusion</span>

<span style="color: rgb(0, 0, 0);">Bien que ce projet ne soit absolument pas demandé à la base, il était essentiel par rapport au sujet que nous avons choisi.</span>

<span style="color: rgb(0, 0, 0);">Nous étions totalement dans l'inconnu lorsque nous avons développé cette application et il a fallu recommencer plusieurs fois, car nous n'avons pas compris tout de suite les problèmes que nous avons rencontrés.</span>

<span style="color: rgb(0, 0, 0);">Cependant, nous sommes très satisfaits du résultat et il a enrichi énormément le projet final.</span>