Index: branch/moisan/sp4a12/main.c
===================================================================
--- branch/moisan/sp4a12/main.c	(revision 346)
+++ branch/moisan/sp4a12/main.c	(revision 347)
@@ -1,3 +1,8 @@
+/*SP4_TP12
+MOISAN Maxence ge3A groupe 5
+date rendu : 19/05/2021
+*/
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <strings.h>
@@ -4,8 +9,23 @@
 #include <math.h>
 #include "trame.h"
 #define M_PI 3.14159265358979323846
+
+//Différentes structures : position et zone
+typedef struct
+{
+    float latitude;
+    float longitude;
+} Position;
+
+Position p_prec; // position du point précédent (utilisé dans le traitement)
+
+typedef struct
+{
+    Position rpos;
+    float vitmax;
+} Zone;
 
-//Trames de tests à modifier si nécessaire.
+//Trames et zones de tests
 char * trames[]=  {"$GPGSV,3,2,10,15,03,077,,18,04,041,42,19,85,271,,20,08,214,*7C",
                     "$GPGSV,3,3,10,22,39,053,50,28,15,320,*7E",
                     "$GPRMC,141914.00,A,4545.6424,N,00306.6036,E,0.4,99.4,010206,,*0C",
@@ -14,34 +34,52 @@
                     "$GPGSA,A,3,,03,,22,14,,01,,18,,,,3.9,3.4,1.9*39",
                     "$GPVTG,99.4,T,,M,0.4,N,0.7,K*57",
                     "$GPZDA,141914.00,01,02,2006,00,00*69",
-                    0};
+                    0};
+Zone zones[]={
+             {{44.7887762, -3.012}, 50}, /* Descripteur de la première zone */
+             {{44.7891220, -3.013}, 70},
+             {{45.7896227, -3.014}, 70},
+             {{45.8791420, -3.014}, 70},
+             {{46.2971220, -3.011}, 70},
+             {{45.75, 3.110000}, 70},
+             {{45.752018, 3.110060}, 70},
+             {{45.754017, 3.110077}, 70},
+             };
 
+int nbre_zone = 8; // nombre de zones dans le tableau de zone test
+
+//fonction comparant 2 chaines de caractères
+//précondition : trame et type 2 chaines de caractère, longueur de type < longueur de trame
+//postcondition : renvoie 1 si la trame commence par la chaîne de caractère type et 0 dans les autres cas
 int trame_cmp(char * trame, char * type)
 {
-    int i = 0;
-    int result = 1;
-    while (type[i]!='\0')
+    int i = 0; //compteur de la boucle
+    int result = 1; //valeur de retour
+    while (type[i]!='\0') //tant que la chaine type n'est pas terminée on exécute le code suivant
     {
-        if(trame[i+1]!=type[i])
+        if(trame[i+1]!=type[i])//si les caractères de trame et type sont identique
         {
-            result = 0;
+            result = 0;//le resultat passe à 0
         }
-        i++;
+        i++;//+1 au compteur
     }
-    return result;
+    return result;//si les caractères de trame et type sont identiques jusqu'à la fin de type on retourne la valeur 0 sinon on retourne la valeur par défaut : 1
 }
 
+//fonction qui renvoie la valeur décimale associée à un caractère donné en paramètre
+//ici on veut que le '0' ASCII soit identique au 0 décimal
 int decode_int(char a)
 {
-    if((a>='0') && (a<='9'))
+    if((a>='0') && (a<='9')) //on veut décoder que les chiffres (de 0 à 9)
     {
-         return (a-48);
+         return (a-48);//le '0' ASCII correspond à la valeur 48 en décimal donc on soustrait juste 48 au caractère que l'on veut décoder
     } else
     {
-        return -1;
+        return -1;//si le caractère n'est pas entre '0' et '9' on retourne -1
     }
 }
 
+//fonction test unitaire qui teste si decode_int fonctionne
 void test_decode_int(void)
 {
     if (decode_int('0')!=0){
@@ -58,28 +96,31 @@
     }
 }
 
+//fonction qui renvoie la valeur décimale des n premiers caractères de la chaîne de caractères ch
 int decode_nombre(char * ch,int n)
 {
-    int i;
-    int res=0;
-    for (i=0;i<n;i++)
+    int i;//le compteur, curseur pour savoir où l'on est dans ch
+    int res=0; //initialisation du résultat
+    for (i=0;i<n;i++)//on parcours ch
     {
-        res += pow(10,(n-i-1))*decode_int(ch[i]);
+        res += pow(10,(n-i-1))*decode_int(ch[i]);//chaque chiffre est décodé avec decode_int puis multiplié par la puissance de 10 selon la place où il est dans ch et on ajoute ça au resultat
     }
-    return res;
+    return res;//on retourne le resultat
 }
 
-int decode_nombre2(char * ch,int n)
+//fonction alternative à la première du même nom
+int decode_nombre2(char * ch,int n)//n est le chiffre auquel on doit s'arrêter
 {
-    int i;
-    int res=0;
-    for (i=0;i<n;i++)
+    int i;//le compteur, curseur pour savoir où l'on est dans ch
+    int res=0;//initialisation du résultat
+    for (i=0;i<n;i++)//on parcours ch jusqu'au n-ième charactère
     {
-        res = 10*res + decode_int(ch[i]);
+        res = 10*res + decode_int(ch[i]);//on multiplie le resultat par 10 puis on ajoute le chiffre d'après préalablement décodé par decode_int
     }
-    return res;
+    return res;//on retourne le resultat
 }
 
+//test unitaire pour savoir si decode_nombre fonctionne
 void test_decode_nombre(void)
 {
     if (decode_nombre("7541",2)!=75){
@@ -100,6 +141,7 @@
     }
 }
 
+//test unitaire pour savoir si decode_nombre2 fonctionne
 void test_decode_nombre2(void)
 {
     if (decode_nombre2("7541",2)!=75){
@@ -120,22 +162,27 @@
     }
 }
 
-float latDMStoDec(char * lat_DMS)
+//fonction convertissant la chaîne de caractère contenant la latitude en nombre flottant
+float latDMStoDec(char * lat_DMS)//lat_DMS est sous la forme : 3723.2475
 {
-    float deg = decode_nombre(lat_DMS,2);
-    float min = decode_int(lat_DMS[2])*10+decode_int(lat_DMS[3])+(0.1*decode_int(lat_DMS[5]))+(0.01*decode_int(lat_DMS[6]))+(0.001*decode_int(lat_DMS[7]))+(0.0001*decode_int(lat_DMS[8]));
-    float latDec = deg+(min/60);
-    return latDec;
+    float deg = decode_nombre(lat_DMS,2);//les degrés de la latitude sont les 2 premiers chiffres on les décode ainsi avec decode_nombre pour les convertir en flottant
+    float min = decode_int(lat_DMS[2])*10+decode_int(lat_DMS[3])+(0.1*decode_int(lat_DMS[5]))+(0.01*decode_int(lat_DMS[6]))+(0.001*decode_int(lat_DMS[7]))+(0.0001*decode_int(lat_DMS[8]));//on décompose les minutes en décodant chiffre après chiffre à l'aide de decode_int
+    float latDec = deg+(min/60);//la latitude en décimal est le nombre de degrés + le nombre de minutes divisé par 60
+    return latDec;//on retourne cette valeur
 }
 
+//test unitaire permettant de voir si latDMStoDec fonctionne (il peut y avoir une erreur de précision)
 void test_latDMStoDec(void)
 {
     if (latDMStoDec("3723.2475")!= 37.387458){
-        printf ("%f Erreur Test latDMStoDec.\n", latDMStoDec("3723.2475"));
+        printf ("Erreur Test latDMStoDec.%f\n", latDMStoDec("3723.2475"));
+        latDMStoDec("3723.2475");
         exit(-1);
     }
 }
 
+//fonction convertissant la chaîne de caractère contenant la longitude en nombre flottant
+//on effectue le même raisonnement sauf que lon_DMS est sous la forme 00306.6036 c'est-à-dire un charactère de plus que lat_DMS
 float lonDMStoDec(char * lon_DMS)
 {
     float deg = decode_nombre(lon_DMS,3);
@@ -144,25 +191,34 @@
     return lonDec;
 }
 
+//test unitaire permettant de voir si lonDMStoDec fonctionne (il peut y avoir une erreur de précision)
+void test_lonDMStoDec(void)
+{
+    if (latDMStoDec("00306.6036")!= 3.11006){
+        printf ("Erreur Test latDMStoDec. %f\n",latDMStoDec("00306.6036"));
+        exit(-1);
+    }
+}
+
+//on rassemble les deux dernières fonctions pour n'en faire qu'une seule
 float lontlatDMStoDec(char * coord)
 {
-    if(decode_nombre(coord,3)>=100){
+    if(decode_nombre(coord,3)>=100)//si il y a 5 chiffres avant la virgule on retourne une longitude
+    {
         return lonDMStoDec(coord);
-    } else {
+    } else //sinon on retourne une latitude
+    {
         return latDMStoDec(coord);
     }
 }
 
-typedef struct
-{
-    float latitude;
-    float longitude;
-} Position;
-
+//fonction qui décode la trame, la décomposant en un ensemble de chaine de caractère "GPGGA" et de position avec la structure définie avant
+//si la trame est validée alors on retourne 1 sinon on retourne 0
 int decode_trame(char *trame, Position *p)
 {
-    if(trame_cmp(trame,"GPGGA")==1)
+    if(trame_cmp(trame,"GPGGA")==1)//si la trame commence par les 5 premiers caractères que l'on souhaite
     {
+        //définition des variable
         char *lon;
         char *lat;
         int i;
@@ -172,71 +228,119 @@
         for(i=0;i<=8;i++){
             lon[i]=trame[i+29];
         }
-        p->latitude = latDMStoDec(*lat);
-        p->longitude = lonDMStoDec(*lon);
+        p->latitude = latDMStoDec(*lat);//on "traduit" la latitude de char à flottant pour pouvoir les utiliser
+        p->longitude = lonDMStoDec(*lon);// on fait de même avec la longitude
         if((p->latitude>=0)&&(p->latitude<=90)){
-                if((p->longitude>=0)&&(p->longitude<=180)){
-                    return 1;
+                if((p->longitude>=0)&&(p->longitude<=180))//vérification dut format de la longitude et de la latitude
+                {
+                    return 1;// la trame est validée
                 } else{
-                    return 0;
+                    return 0;// la trame n'est pas validée
                 }
         } else{
-            return 0;
+            return 0;// la trame n'est pas validée
         }
     } else {
-        return 0;
+        return 0;// la trame n'est pas validée
     }
 }
 
+// test unitaire pour savoir si decode_trame fonctionne
 void test_decode_trame(void)
 {
-    struct Position *p1;
-    if (decode_trame("$GPGLL,4545.6419,N,00306.6043,E,141921.00,A*04",p1)!= 0){
+    Position p;
+    if (decode_trame("$GPGLL,4545.6419,N,00306.6043,E,141921.00,A*04",&p)!= 0){
         printf ("Erreur Test decode_trame.\n");
         exit(-1);
     }
-    struct Position *p2;
-    if (decode_trame("$GPGGA,141922.00,4545.1810,N,00306.6046,E,1,05,3.4,500.6,M,,M,,*74",p2)!= 1){
+    if (decode_trame("$GPGGA,141922.00,4545.1810,N,00306.6046,E,1,05,3.4,500.6,M,,M,,*74",&p)!= 1){
         printf ("Erreur Test decode_trame.\n");
         exit(-1);
-    } else {
-        struct Position *p3;
-        decode_trame("$GPGGA,141922.00,4545.1810,N,00306.6046,E,1,05,3.4,500.6,M,,M,,*74",p3);
-        //printf("longitude : %f \n latitude : %f \n",p3->latitude, p3->longitude);
     }
 }
 
+
+//petite fonction permettant de transformé les degrés en radiant
 float deg2rad(deg)
 {
     return deg * (M_PI/180);
 }
 
+//fonction qui calcul la distance entre 2 position
 float calcule_distance(Position p_1, Position p_2){
-    float lonP1 = deg2rad(p_1.longitude);
+    float lonP1 = deg2rad(p_1.longitude);//on convertit en radian les longitudes et latitudes
     float lonP2 = deg2rad(p_2.longitude);
     float latP1 = deg2rad(p_1.latitude);
     float latP2 = deg2rad(p_2.latitude);
-    float r=6371;
-    float d = r * acos(sin(latP1)*sin(latP2)+cos(latP1)*cos(latP2)*cos(lonP1-lonP2));
-    return d;
+    float r=6371; //rayon de la terre
+    float d = r * acos(sin(latP1)*sin(latP2)+cos(latP1)*cos(latP2)*cos(lonP1-lonP2));//on applique la formule
+    return d; //on retourne la distance en km
 }
 
+//on calcul la vitesse correspondant au parcours de la distance entre les points p_1 et p_2 pendant 1s
 float calcule_vitesse(Position p_1, Position p_2)
 {
-    float d = calcule_distance(p_1, p_2);
-    return d*3600;
+    float d = calcule_distance(p_1, p_2);//on utilise la fonction précédente pour calculer la distance
+    return d*3600;//on multiplie cette distance par le nombre de seconde dans une heure car on veut la distance en km/h
 }
+
+//fonction qui renvoie le numéro de la zone la plus proche du point p ainsi que sa distance
+int distance_a_la_proche_zone(Position p, Zone r[],int nb_zones, float *d)
+{
+    int i,res = 0; //curseur pour se déplacer dans le tableau des zones et initialisation du résultat
+    if (nb_zones == 0) //s'il n'y a pas de zones dangereuses
+    {
+        return -1;//on revoie -1
+    } else
+    {
+        *d = calcule_distance(p,r[0].rpos);//on initialise la distance la plus proche à la distance entre le point p et la première position
+        for (i=1;i<nb_zones;i++)//on parcours les zones
+        {
+            if(calcule_distance(p,r[i].rpos)<*d)//on estime la valeur de la distance et si elle est plus petite on entre dans cette boucle
+            {
+                *d = calcule_distance(p,r[i].rpos);//nouvelle distance plus petite
+                res = i;// resultat devient le numéro de la zone la plus proche
+            }
+        }
+        return res;//on retourne ce numéro
+    }
+}
 
 //Fonction à modifier !!!!!
-void traitement(char * trame)
+void traitement(char * trame) //traitement qui accepte ou non la trame, calcul la vitesse et la distance à la zone la plus proche et, si cette distance est inférieure à un seuil et que la vitesse du véhicule est supérieure à celle définie pour cette zone, de déclencher une alarme.
 {
+    int res;
+    float v,d,seuil = 50;//initialisation des variables utiles v(vitesse), d(distance) et du seuil à ne pas dépasser
+    Position p;//position à l'instant présent, à l'instant précédent p_prec
+
+    static int cpt=0;
+    cpt++;
+
     if(trame_cmp(trame,"GPGGA")==1)
     {
             printf ("> %s\n",trame);
+            res = decode_trame(trame,&p);
+            if (res==1)//si la trame est validée
+            {
+                printf("Votre position est est de : %f en longitude et %f en latitude\n",p.longitude,p.latitude);//on écrit la position de la voiture
+                v = calcule_vitesse(p,p_prec);//calcul de la vitesse
+                printf("Vous roulez à %f\n",v);//on indique sa vitesse
+                res = distance_a_la_proche_zone(p, zones, nbre_zone,&d);//on indique le numéro de la zone la plus proche
+                if ((d<seuil)&&(v>zones[res].vitmax))//si la distance de la zone dangereuse est plus faible que le seuil et que l'on roule à une vitesse supérieur à celle indiquée par la zone
+                {
+                    printf("Alarme ON au niveau de la zone %d \n",res);//Alarme ON
+                } else
+                {
+                    printf("Alarme OFF");//Alarme OFF
+                }
+            }
+            p_prec.longitude = p.longitude;//le point precédent devient le point que l'on vient de traiter
+            p_prec.latitude = p.latitude;//le point precédent devient le point que l'on vient de traiter
     }
 }
 
 //Ajouter vos tests unitaires dans cette fonction.
+//On exécute les test unitaire pour sacoir si on a fait des erreurs
 void tests_unitaires(void){
     if (5!=5){
         printf ("Erreur Test unitaire basique.\n");
@@ -261,7 +365,9 @@
     test_decode_nombre();
     test_decode_int();
     test_latDMStoDec();
+    test_lonDMStoDec();
     test_decode_nombre2();
+    test_decode_trame();
 }
 
 // Ne pas modifier cette fonction
