fixed all the last big bugs before going to PWA

This commit is contained in:
2023-06-01 14:30:30 +02:00
parent 3f4b82301d
commit bef8b9d635
27 changed files with 142 additions and 2979 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

+103 -1
View File
@@ -338,6 +338,10 @@ J'ai mis une durée arbitraire de deux jours, mais je ne sais pas vraiment combi
----
### Outils utilisés
[A Remplir]
### Technologies utilisées
Dans ce projet différents choix ont été faits pour ce qui est des technologies.
@@ -1939,7 +1943,105 @@ Les possibilitées sont infinies !
----
[A remplir au fur et à mesure de la création des tests]
Alors la on arrive à la GROSSE erreur de ce projet...
Si je ne pouvais changer qu'une seule chose à ma facon de faire le projet après coup c'est ici que je ferai le changement.
Les tests sont d'une importance absolument capitale mais si ils sont bien faits, c'est surtout un moyen ultra efficace de vérifier que du nouveau code est performant et est beaucoup plus pratique à utiliser.
Je pense sans rire que j'aurais pu gagner plusieurs jours de travail si j'avais travaillé différemment vis-a-vis des tests.
### Comment ca c'est passé
Dès la création du planning prévisionnel j'ai fait une erreur capitale. J'ai mis les tests en fin de developpement des features... Et je ne leur ai laissé que très peu de temps tout en les mettant au milieu du chemin critique ce qui les rends particulièrement vulnérables si une tâche du chemin critique est retardée.
En fait dans ce projet je voulais surtout éviter de faire comme certains projets que l'on a pu avoir pendant notre formation. C'est à dire que je ne voulais surtout pas oublier la doc. Alors j'ai agencé le projet pour commencer par les fondations de la doc, puis en incluant les périodes de programmation et entre ces dernière ajouter des Tests dans les trous. Le soucis c'est que du coup les projets étaient un peu le dernier truc dont je devais me soucier ce qui a été une très mauvaise idée.
Je me suis retrouvé à devoir mordre sur les jours de tests car les tâches de programmation mettaient plus de temps que prévu (qui elles-même auraient pû être plus courte avec une bonne utilisation des tests) et je mme suis retrouvé à passer outre les tests pour avancer sur le reste du projet.
J'ai donc du en panique à la toute fin du projet construire quelques tests "unitaires" dont l'utilité est très limitée car tout le travail a déja été fait et que vu la complexité qu'a pris le projet, faire de vrais tests unitaires est devenu un peu trop compliqué pour valoir le coup.
Les seuls tests "unitaires" (Je l'écris entre quotes car ce ne sont pas vraiment des tests unitaires mais plutôt des tests tout courts car ils ne sont pas spécifiques) qu'il y a dans le projet final sont des tests exclusivement tournés sur l'OCR. Ils sont déja vraiment pratiques car cela me permet de tester d'autres algorythmes d'OCR et voir si les résultats sont meilleurs ou non mais c'est juste un peu trop tard quoi...
Les tests unitaires que j'ai implémentés sont un peu tous pareils au niveau du fonctionnement :
1. On choisit une image dans une liste d'images préparées qui sont scensée représenter le type de données rencontrées par l'application en temps normal
2. On lis le nom de l'image que j'ai mis manuellement en indiquant ce qui était marqué sur l'image
3. On fait un coup d'OCR sur l'image et on compare ce résultat avec la valeur que l'on est scensé retrouver
En pratique on est sur un code de ce style :
```Csharp
[TestMethod()]
public void SectorOCR_Test()
{
string directory = @"./../../TestImages/Sectors/";
foreach (string file in Directory.GetFiles(directory))
{
Bitmap image = (Bitmap)Image.FromFile(file);
DriverSectorWindow sectorsWindow = new DriverSectorWindow(image, new Rectangle(0, 0, image.Width, image.Height), 1, true);
string[] paths = file.Split('/');
string fileName = paths[paths.Length - 1];
fileName = fileName.Replace(".png", "");
int timeMS = (int)sectorsWindow.DecodePng();
string time = Reader.ConvertMsToTime(timeMS);
string[] checkDigits = fileName.Split('_');
string[] digitsToCheck = time.Split(':');
if (time == "0:00:000")
{
Assert.AreEqual(0, Convert.ToInt32(checkDigits[0]));
}
else
{
//The ConvertMSToTime will always return three chars so we need to make the checkDigits be also three chars
while (checkDigits.Length != 3)
checkDigits = new[] { "0" }.Concat(checkDigits).ToArray();
for (int i = 0; i < checkDigits.Length; i++)
{
//We need to convert to int first because sometimes we have "08" and "8" and in string its not the same but in int it is
Assert.AreEqual(Convert.ToInt32(checkDigits[i]), Convert.ToInt32(digitsToCheck[i]));
}
}
}
}
```
Tout le code supplémentaire qui ne fait pas partie des étapes citées est juste la pour manipuler le format des résultats pour qu'il soit comparable.
!["Exemple d'échantillons pour les tests"](./Images/Screens/DataSetGaps.png)
Ce qui est pratique avec cette approche c'est qu'il est très facile de rajouter des cas spécifiques et voir comment le programme les gère.
Si je vois que un certain nombre est souvent mal reconnu je peux faire exprès de le mettre dans le dossier et modifier mon code d'OCR jusqu'à ce que le test passe.
Si j'avais eu plus de temps j'aurais sûrement pu ajouter de vrais tests unitaires qui testent des fonctions très précises. Par exemple verifier que les différentes Windows sont bien appelées et que les zones se créent correctement ou même plus simplement que la lecture du JSON au démarrage marche bien.
Il faut savoir que même si je n'ai pas eu l'occasion d'écrire beaucoup de tests sous forme de code. Toute la phase de développement de l'OCR j'ai passé plus d'une heure par jour à analyser les résultats. Je gardais toutes les images des WINDOWS et je notais dans le nom du fichier ce que l'algorythme trouvais et je passais en revue manuellement les centaines de résultats pour isoler ceux qui posaient problème.
C'est comme ca que je me suis rendu compte par exemple que, avec cette police, les 4 et les 1 étaient souvent confondus. Donc même si les tests automatisés sont clairement insuffisant par rapport à ce que j'aurais peut-être du faire, j'ai passé énormément de temps à tester mon application.
### Comment ca aurait du se passer
Si je devais refaire ce projet aujourd'hui je pense que j'utiliserais un peu la même technique que pour la doc. J'aurais mis les tâches de Tests directement au début du projet et j'aurais determiné le squelette de l'application par la même occasion.
Je pense que j'aurais mis trois jours pour écrire tous les tests dont j'aurais besoin et j'aurais fait une stratégie de TDD (Test Driven Developpement) par ce que je pense que ca marcherait vraiment super bien sur ce type de projet.
J'aurais pris je pense 5 une dixaine d'images complêtes de la F1TV de plusieurs GP différents et j'aurais mis toutes les fenêtres découpées dans des fichiers avec des tests comme ceux que j'ai fait pour ce projet. Et comme ca je saurai que mon algo est bon uniquement quand il aura réussi à passer tous les tests.
Cela règlerait le soucis que j'ai eu le plus : Me retrouver à devoir changer l'OCR 5 fois par ce que à chaque fois que je développe une nouvelle feature je me rends compte d'une faiblesse mon algorythme...
Non seulement j'aurai eu beaucoup plus de facilité à avancer sur le projet, mais en plus je pense que cela m'aurait fait gagner énormément de temps non seulement car je n'ai plus à tester tout à la main mais en plus par ce que ca veut dire que quand l'OCR passe les tests je n'ai plus jamais à m'en soucier.
### Lecons
Je pense que dans mes futurs projets je mettrai les tests en début de projet plutôt que à la fin et je ferai en sorte qu'ils fassent partie du chemin critique et que je ne puisse pas passer à côté sous pretexte que "Je n'ai pas le temps".
Ecrire des tests c'est jamais marrant et c'est encore moins marrant quand ils nous empêchent d'avancer. Mais je suis convaincu que au final c'est un gain de temps et de sérénité incontournable.
[INSERER MEME SUR LES TESTS UNITAIRES]
## Résumé des difficultés techniques
+39
View File
@@ -3027,3 +3027,42 @@ Bon j'ai pu rendre à M.Jayr mon evaluation intermédiaire et j'ai fait les dern
Il faut peut-être aussi que je parle vite fait dans la partie Emulation que j'ai du changer les variables d'environnement pour faire fonctionner le système en 4K.
## Mercredi 31 Mai 2023
Doc
## Jeudi 1 Juin 2023
Bon je me suis rendu compte que je n'avais fait vraiment aucuns tests et que c'est franchement bof. Je pense que ce que je devrais faire pour faire des tests unitaires c'est prendre des exemples de chaque type de windows possibles en plusieurs exemplaires. Ensuite je note le résultat que j'attends et je regarde si ca me retourne la bonne valeur.
Mais ca veut dire que ca va me prendre pas mal de temps de tout mettre en place mais ca m'aurait sûrement fait gagner beaucoup de temps si je l'avais fait dès le début...
Je pense que une bonne idée serait de prendre trois Grand Prix et de prendre une photo de chaque type de window au début et à la fin.
Plus je regarde plus je me rend compte que ce pojet aurait carrément du être en TDD (Test Driven Developement) par ce que ca m'aurait fait gagner un temps FOU.
OK JE SUIS DEBILE POURQUOI J'AI PAS FAIT CA PLUS TÔT ???
En fait ce que j'aurais du faire c'est prendre de gros échantillons de toutes les types de windows et j'aurais un parfait framework pour savoir si j'ai amélioré mon OCR ou non.
Voici les exemples que je vais utiliser pour verifier le bon fonctionnement de l'OCR :
!["Dataset Ecarts"](./Images/Screens/DataSetGaps.png);
!["Dataset Tours"](./Images/Screens/DataSetLaps.png);
!["Dataset Noms"](./Images/Screens/DataSetNames.png);
!["Dataset Positions"](./Images/Screens/DataSetPositions.png);
!["Dataset Sectors"](./Images/Screens/DataSetSectors.png);
!["Dataset Tyres"](./Images/Screens/DataSetTyres.png);
Je pense que c'est un set assez correct car j'ai essayé de prendre un peu tous les cas possibles.
Le seul qui m'inquiète un peu c'est celui des pneus mais bon. C'est aussi celui qui m'inquiète le plus en temps normal.
Non mais c'est juste génial les tests en fait... j'avais pas vu que parfois ma detection de GAP TO LEADER comprenait le "+1:34.567" en "61:34.567" car le '+' était interprêté comme un 6. Sans les tests je ne m'en serais pas rendu compte.
Ce qui est génial c'est que ca veut dire que si je veux améliorer mon OCR j'ai juste à mettre plus d'exemples dans le dossier de tests et de run les tests et voir ou il a des soucis. C'est un peu tard mais ca m'aurait fait gagner TELLEMENT de temps c'est absolument ridicule.