Récupération et traitement des fichiers csv "vaccination à ce jour"

Ces fichiers sont de petite taille. Ils contiennent seulement des données pour la vaccination à la dernière date disponible.

Comme tous les fichiers csv, ils commencent par une ligne d'entête qui décrit sommairement les champs des lignes qui suivront.

Vérifications communes aux fichiers concernés

A chaque fichier .csv qui concerne la vaccination à ce jour est associé un fichier vide de suffixe .date

L'intérêt de se fichier est son heure de dernière mise à jour.
On commence par la vérifier.
    // fichier qui mémorise la date et l'heure du dernier test de l'url
    $fdate = DIR_CSV."/vacsi-tot-a-fra.date";

    // si on a appelé cette fonction depuis moins de 30 minutes
    if (filemtime ($fdate) + TEMPO_TESTS > time ())
        // on ne recommence pas de suite le même traitement
        return;
      
Si le dernier appel de la fonction de vérification date de moins de TEMPO_TESTS seconde, avec TEMPO_TESTS défini dans constantes.php
    define ('TEMPO_TESTS', 1800); // attente en secondes avant de retester un fichier de référence
      
soit moins d'une demi heure, on conserve la version du fichier .csv mémorisé localement.

Dans le cas contraire, on commence par actualiser l'heure de dernière vérification :
    // mémoriser la date et l'heure du traitement qu'on va effectuer
    $descdate = fopen ($fdate, "w");

    // on se contente de changer la date de mise à jour d'un fichier vide
    if ($descdate)
        fclose ($descdate);
      
Il faut ensuite vérifier si le fichier sur le site de référence concerne une date ultérieure à celle mémorisée dans le fichier local.

Si c'est le cas, on le mettra à jour.

Dans le cas du fichier vacsi-tot-a-fra.csv qui mémorise les taux de vaccination pour les différentes classes d'âge, le code suivant permet de récupérer les dates à comparer :
    // url du fichier de référence
    $url = SITE_REF.vacsi_tot_a_fra;

    // ouvrir cet url en lecture
    $descurl = fopen ($url, "r");

    // si l'ouverture s'est bien passée
    if ($descurl)
    {
        // sauter la première ligne de l'url
        fgets ($descurl, LG_MAX_CSV * 2);

        // lire la 2ème ligne de l'url en oubliant "FR;"
        $ligne_url = substr (fgets ($descurl, LG_MAX_CSV), 3);

        // séparer les différents champs de la ligne
        // on prévoie que des champs supplémentaires pourront apparaitre
        $args = explode (";", trim ($ligne_url), 20);

        // mémoriser la date
        $date_url = $args [1];

        // fichier local contenant la version précédente de l'url
        $chemcsv = DIR_CSV."/vacsi-tot-a-fra.csv";

        // ouvrir ce fichier en lecture
        $descscv = fopen ($chemcsv, "r");

        // si l'ouverture s'est bien passée
        if ($descscv)
        {
            // récupérer la date présente dans le fichier local
            $date_csv = trim (fgets ($descscv, 20));

            // déja terminé avec ce fichier
            fclose ($descscv);
        }
      
Examinons ce code en détail.

Tout d'abord, on ouvre en lecture le fichier du site de référence. On saute la première ligne (description des champs du fichier) dont on n'a pas besoin, et on lit la ligne suivante :
    // url du fichier de référence
    $url = SITE_REF.vacsi_tot_a_fra;

    // ouvrir cet url en lecture
    $descurl = fopen ($url, "r");

    // si l'ouverture s'est bien passée
    if ($descurl)
    {
        // sauter la première ligne de l'url
        fgets ($descurl, LG_MAX_CSV * 2);

        // lire la 2ème ligne de l'url en oubliant "FR;"
        $ligne_url = substr (fgets ($descurl, LG_MAX_CSV), 3);
      
Pour récupérer la date mentionnée dans cette ligne, on peut le faire en une instruction. Il suffit de récupérer 10 caractères après le premier ; récupéré dans la ligne lue :
    // extraire la date de cette ligne
    $date_url = substr ($ligne_url, strpos ($ligne_url, ";") + 1, 10);
      
C'est ce qui était fait au début de ce site.

Actuellement, c'est fait d'une manière plus élégante. On sépare et on mémorise dans un tableau les différents champs de la ligne du fichier csv. La date est le 2ème champ, c'est à dire le champ numéro 1 puisqu'en informatique, on commence à compter à partir de 0.
    // séparer les différents champs de la ligne
    // on prévoie que des champs supplémentaires pourront apparaitre
    $args = explode (";", trim ($ligne_url), 20);

    // mémoriser la date
    $date_url = $args [1];
      
On ouvre alors en lecture le fichier .csv local et on récupère la date qui est mémorisée dans sa première ligne avant de refermer ce fichier.
    // fichier local contenant la version précédente de l'url
    $chemcsv = DIR_CSV."/vacsi-tot-a-fra.csv";

    // ouvrir ce fichier en lecture
    $descscv = fopen ($chemcsv, "r");

    // si l'ouverture s'est bien passée
    if ($descscv)
    {
        // récupérer la date présente dans le fichier local
        $date_csv = trim (fgets ($descscv, 20));

        // déja terminé avec ce fichier
        fclose ($descscv);
    }
      
Si les deux dates sont différentes, ça signifie que sur le site de référence, il y a une version des données plus récente que celles mémorisée localement.

Dans ce cas, (et dans ce cas seulement), on va mettre à jour le fichier local.

Pour cela, on crée un nouveau fichier local de suffixe .new .

On commence par recopier la date récupérée du site de référence qui va constituer la première ligne de ce fichier, puis on récupère le nombre de doses de vaccin prises en compte dans le fichier de référence.

Ensuite, le traitement à effectuer est spécifique à chaque fichier .csv .
    // si ces dates sont différentes
    if ($date_url != $date_csv)
    {
        // on va reconstruire le fichier csv local à partir de l'url

        // pour l'instant, son nom est provisoire
        $nouvcsv = DIR_CSV."/vacsi-tot-a-fra.new";

        // ouvrir ce fichier en écriture
        $descscv = fopen ($nouvcsv, "w");

        if ($descscv)
        {
            // recopier la date dans la première ligne
            fputs ($descscv, $date_url."\n");

            // trouver le nombre de doses mémorisées
            $doses = (count ($args) - 3) / 2;

            // traitement spécifique pour chaque fichier .csv
            ...

            // remplissage fichier terminé
            fclose ($descscv);

            // on remplace l'ancien fichier par le nouveau
            rename ($nouvcsv, $chemcsv);
        }
    }
      
Toutefois, les différents fichiers de référence concernant la vaccination à ce jour ont une structure commune. Au départ, ils ont mémorisé deux injections, puis 3, puis 4. Mais pour chaque nouvelle dose, la même logique a été utilisée pour ordonner les champs les uns par rapport aux autres.

La première version de ce site a été mise au point pour 2 doses de vaccin. Mais peu après sa mise en ligne, une 3ème dose a été rajoutée obligeant notamment à corriger les fonctions permettant de fabriquer les fichiers csv locaux.

Puis il y a eu la 4ème dose qui n'est pas apparue au même moment dans les fichiers de référence par classe d'âge et dans ceux ou le classement obéit à un critère géographique.

Dans la version actuelle du site, le nombre de doses de vaccin est détecté automatiquement grâce à l'instruction suivante :
    // trouver le nombre de doses mémorisées
    $doses = (count ($args) - 3) / 2;
      
L'emploi de la fonction explode (...) au moment où on a récupéré la date dans la ligne permet d'obtenir facilement le nombre de champs du fichier csv de référence, et de trouver le nombre de doses de vaccin qu'il mémorise.

Ensuite, pour sélectionner et traiter les champs à recopier dans le fichier cvs local, la fonction présente dans selchamps-jour.php permet de faire le même traitement pour cacune des lignes de tous les fichiers de référence qui donnent l'état de la vaccination à ce jour :
<?php
    // réordonner le champ date et supprimer les champs inutiles

    function selchamps_jour ($ligne, $doses)
    {
        // extraire les différents champs de la ligne
        // on prévoie que des champs supplémentaires pourront apparaitre
        $args = explode (";", trim ($ligne), 20);

        // traitement rajouté à partir de la 5ème dose
        // deux colonnes sont à fusionner pour cette dose là
        if ($doses >= 5)
        {
            fusion_colonne ($args, $doses + 1);
            fusion_colonne ($args, $doses + $doses + 2);
        }

        // population : une valeur entière !
        $pop = round ($args [$doses + 2], 0);

        // mettre en forme la ligne

        // critère de sélection et population
        $ligne = $args [0].";".$pop;

        // nombre d'injections pour les différentes doses (valeur entière !)
        // suivi du taux de vaccination pour les différentes doses
        for ($i = 1; $i <= $doses; $i ++)
            $ligne = $ligne.";".round ($args [$i + 1], 0)."-".$args [$i + $doses + 2];

        // fin de la ligne
        $ligne = $ligne."\n";

        // retourner la ligne mise en forme
        return ($ligne);
    }
?>
      
On remarque notamment que :

Remarque : Même si la fabrication du nouveau fichier local ne prend qu'une fraction de seconde, en remplissant d'abord un autre fichier, on évite qu'un autre utilisateur qui consulterait la même page au même moment se retrouve avec aucune donnée disponible.

Le fichier vacsi-tot-a-fra (vaccination par classe d'âge)

Le fichier csv de référence a le contenu suivant :



Afin d'effectuer le moins de traitements possible lorsqu'on affiche les taux de vaccination par classe d'âge, on veut enregistrer un fichier au format suivant :
2023-07-10
04;3574109;6382-0.2;3950-0.1;1020-0.0;40-0.0;30-0
09;4012275;138559-3.5;111656-2.8;2165-0.1;40-0.0;106-0
11;1704735;172316-10.1;143625-8.4;9125-0.5;263-0.0;2133-0.1
17;5129684;4291858-83.7;4163779-81.2;952707-18.6;23591-0.5;48639-0.9
24;5614235;5388831-96.0;5259644-93.7;3663803-65.3;101819-1.8;83172-1.4
29;3702869;3650786-98.6;3566033-96.3;2432578-65.7;94023-2.5;76360-2.1
39;8241517;7723290-93.7;7571838-91.9;5332412-64.7;258656-3.1;216741-2.6
49;8569953;8043522-93.9;7936716-92.6;6208861-72.4;439709-5.1;376586-4.3
59;8890627;8375482-94.2;8295960-93.3;7121367-80.1;1176574-13.2;926694-10.4
64;4168072;3867900-92.8;3836906-92.1;3461860-83.1;1400398-33.6;1032936-24.8
69;3897907;3620115-92.9;3593097-92.2;3317501-85.1;1655345-42.5;1318445-33.8
74;3705621;3490360-94.2;3463657-93.5;3238224-87.4;1829615-49.4;1529655-41.3
79;2523115;2209513-87.6;2189494-86.8;2041760-80.9;1235547-49.0;1098672-43.6
80;4128852;3698749-89.6;3636907-88.1;3258842-78.9;2014687-48.8;1881596-45.6
0;67863570;54677681-80.6;53773279-79.2;41042237-60.5;10230314-15.1;8591767-12.7
      
La première ligne du fichier de référence qui indique la liste des champs n'est pas conservée.

Dans les ligne qui suivent, le premier champ qui contient "FR" (le pays) ne nous sert pas. On va donc l'ignorer aussi en sautant 3 caractères au début de chaque ligne lue :
    // lire la première ligne de l'url en oubliant "FR;"
    $ligne_url = substr (fgets ($descurl, LG_MAX_CSV), 3);
      
La date extraite de la ligne qui suit est recopiée seule dans la première ligne du nouveau fichier.

Le fichier de référence est presque trié par classes d'âge croissantes mais pas tout à fait : la classe d'âge notée 09 (de 5 à 9 ans) est positionnées entre les classes d'âge 59 et 64.

À cause de ça, on va :
D'autre part, on veut conserver en fin de fichier la ligne qui concerne le total général, toutes classe d'âge confondues.

Les lignes concernant une classe d'âge particulière commencent par 2 chiffres qui représentent l'âge maximum dans la classe d'âge, sauf pour 80 où c'est l'âge minimum, suivies d'un ; (délimiteur de champ) qui est donc en 3ème position.

La classe d'âge correspondant au total général commence par 0; (le ; est en 2ème position).
Ce critère permet de détecter quand toutes les classes d'âge ont été mémorisées et de traiter la dernière ligne du fichier de référence séparément.

On commence d'abord par par récupérer les champs intéressants des lignes correspondant aux différentes classes d'âge et à les mémoriser dans un tableau.
    // on va mémoriser les lignes du fichier de référence
    // pour les trier par âge croissant
    $tabligne = array ();

    // tant que la dernière ligne lue fait référence à une classe d'âge
    while (substr ($ligne_url, 2, 1) == ";")
    {
        // corriger la ligne en supprimant le champ date, la partie
        // décimale de la population (!) et réordonner les champs
        $ligne_url = selchamps_jour ($ligne_url, $doses);

        // la mémoriser
        array_push ($tabligne, $ligne_url);

        // lire la ligne suivante de l'url en oubliant "FR;"
        $ligne_url = substr (fgets ($descurl, LG_MAX_CSV), 3);
    }

    // trier le tableau par classes d'âge croissantes
    sort ($tabligne);
      
Ensuite, on trie ces lignes par classe d'âge croissante et on copie le résultat dans un fichier.
    // trier le tableau par classes d'âge croissantes
    sort ($tabligne);

    // compléter le fichier par classes d'âge croissantes
    foreach ($tabligne as $ligne_csv)
        fputs ($descscv, $ligne_csv);
      
Pour terminer, on rajoute la dernière ligne du fichier de référence qui correspond à toutes les classes d'âge confondues.
    // traiter comme les autres la ligne tous âges confondus
    $ligne_url = selchamps_jour ($ligne_url, $doses);

    // la rajouter
    fputs ($descscv, $ligne_url);
      

Le fichier vacsi-tot-dep (vaccination par département)

Le fichier csv de référence a la même structure que le fichier vacsi-tot-a-fra.csv et, comme lui, est presque bien ordonné, mais pas tout à fait :
dep;jour;n_tot_dose1;n_tot_complet;n_tot_rappel;pop;couv_tot_dose1;couv_tot_complet;couv_tot_rappel
01;2021-11-11;419202;404740;31526;656955.0;63.8;61.6;4.8
02;2021-11-11;388916;380867;32230;526050.0;73.9;72.4;6.1
...
19;2021-11-11;194316;191227;19871;240336.0;80.9;79.6;8.3
21;2021-11-11;408228;397850;38035;532886.0;76.6;74.7;7.1
22;2021-11-11;516182;498941;52530;596186.0;86.6;83.7;8.8
...
29;2021-11-11;756105;749538;64372;906554.0;83.4;82.7;7.1
2A;2021-11-11;125603;122039;13683;162421.0;77.3;75.1;8.4
2B;2021-11-11;125444;123115;14877;182258.0;68.8;67.5;8.2
30;2021-11-11;553627;544407;49781;748468.0;74.0;72.7;6.7
31;2021-11-11;995655;981803;64502;1400935.0;71.1;70.1;4.6
...
94;2021-11-11;1078020;1053453;68772;1406041.0;76.7;74.9;4.9
95;2021-11-11;936762;902459;54277;1248354.0;75.0;72.3;4.3
971;2021-11-11;133687;123494;5306;376879.0;35.5;32.8;1.4
972;2021-11-11;133433;123289;6175;358749.0;37.2;34.4;1.7
...
978;2021-11-11;13288;11935;416;35334.0;37.6;33.8;1.2
      
Il n'y a pas le champ "FR" en début de ligne, on n'aura dans pas à le supprimer.

Les départements sont presque dans l'ordre mais :
On commence par mémoriser dans un tableau les informations qui nous intéressent pour les département de métropole dans l'ordre dans lequel ils apparaissent.
    // on va mémoriser les lignes du fichier de
    // référence par numéro de département croissant
    $tabligne = array ();

    // répéter
    do
    {
        // extraire le numéro de département
        $dep = substr ($ligne_url, 0, 2);

        // sélectionner dans la ligne les champs à garder
        $ligne_url = selchamps_jour ($ligne_url, $doses);

        // la mémoriser
        array_push ($tabligne, $ligne_url);

        // lire la ligne suivante de l'url
        $ligne_url = fgets ($descurl, LG_MAX_CSV);
    }
    // jusqu'à tous les départements de métropole mémorisés
    while ($dep < 95);
      
Ensuite, en utilisant la possibilité d'accéder au tableau case par case (la première case à le numéro 0 et la dernière le numéro 95, soit 96 départements en tout), on va les recopier dans les fichier dans l'ordre suivant :
    // trier le tableau par numéros de départements
    $i = 0;

    // les 19 premiers
    do
        fputs ($descscv, $tabligne [$i]);
    while (substr ($tabligne [$i++], 0, 2) < 19);

    // 2A et 2B (Corse)
    fputs ($descscv, $tabligne [$i + 9]);
    fputs ($descscv, $tabligne [$i + 10]);

    // les 9 suivants
    do
        fputs ($descscv, $tabligne [$i]);
    while (substr ($tabligne [$i++], 0, 2) < 29);

    // les derniers
    $i = $i + 2;

    while ($i <= 95)
        fputs ($descscv, $tabligne [$i++]);
      

Le fichier vacsi-tot-reg (vaccination par région)

Le fichier csv de référence a le contenu suivant :



Il commence par des données concernant les DOM qui sont numérotés de 01 à 08 avec le 05 (Saint-Pierre-et-Miquelon) manquant.

Ensuite, il y a les données concernant les régions de métropole avec des numéros de région compris entre 11 et 94 qui correspondent à un code INSEE.

Toutefois, en décembre 2021 et janvier 2022, les informations concernant les DOM ont été supprimées. En conséquence, ce web site a été modifié pour afficher les informations au 30 novembre pour les DOM.

Le script php testmaj-tot-reg.php générait à l'origine le fichier vacsi-tot-reg.csv (pour les régions de métropole) et le fichier vacsi-tot-dom.csv pour les départements d'outre-mer.

Avec la disparition provisoire des informations sur ces derniers, j'ai simplifié ce script php pour qu'il ne traite que les régions. Un script php distinct testmaj-tot-dom.php a été rajouté le 1er février 2022 lorsque les informations sur les DOM ont été de nouveau disponibles.

À partir du fichier csv de référence, on va créer un fichier csv local pour les régions dans lesquels les noms des régions sont exprimés en clair. Ce qui donnera ceci :
2023-07-10
Auvergne-Rhône-Alpes;8153233;6285574-77.1;6224002-76.3;4750314-58.3;1165924-14.3;969405-11.9
Bourgogne-Franche-Comté;2785393;2196404-78.9;2174513-78.1;1714988-61.6;452095-16.2;360268-13
Bretagne;3402932;2846216-83.6;2819146-82.8;2271708-66.8;653662-19.2;564662-16.6
Centre-Val de Loire;2564915;2080553-81.1;2060196-80.3;1661554-64.8;479690-18.7;404711-15.8
Corse;349465;237866-68.1;234365-67.1;178669-51.1;33016-9.4;26436-7.6
Grand Est;5542094;4328879-78.1;4285112-77.3;3391386-61.2;828268-14.9;658818-11.9
Hauts-de-France;5987172;4747655-79.3;4699762-78.5;3717960-62.1;898091-15.0;727452-12.1
Ile-de-France;12395148;9391476-75.8;9281878-74.9;6941127-56.0;1584859-12.8;1426501-11.5
Normandie;3307286;2737387-82.8;2710667-82.0;2182308-66.0;585978-17.7;489427-14.8
Nouvelle-Aquitaine;6081985;4977859-81.8;4926384-81.0;3936195-64.7;1120087-18.4;956228-15.8
Occitanie;6053548;4672749-77.2;4618622-76.3;3583181-59.2;922001-15.2;768983-12.7
Pays de la Loire;3873096;3165874-81.7;3137091-81.0;2492257-64.3;686661-17.7;587261-15.1
Provence-Alpes-Côte d’Azur;5131187;3891910-75.8;3836539-74.8;2897949-56.5;700200-13.6;566084-11
      
On commence par sauter les lignes du fichier de référence concernent les DOM.
    // tant que la ligne lue concerne un DOM (s'il y en a dans le fichier)
    while ($ligne_url [0] == "0")
        // passer à la ligne suivante
        $ligne_url = fgets ($descurl, LG_MAX_CSV);
      
Les codes pour les régions ne suivant pas l'ordre alphabétique des noms, on va mémoriser les ligne issues du fichier csv de référence dans un tableau, afin de pouvoir faire un tri alphabétique.

Pour convertir les quelques numéros de régions qui sont compris entre 11 et 94 en nom de région, on va utiliser l'instruction switch.
    // on va mémoriser les lignes du fichier de référence dans un
    // tableau pour trier les régions par ordre alphabétique des noms
    $tabligne_reg = array ();

    // trouver le nombre de doses mémorisées
    $doses = (count ($args) - 3) / 2;

    // tantque non fin du fichier de référence
    while ($ligne_url)
    {
        // les numéros de région ne sont pas contigus utilisation
        // d'un switch - case pour mettre leur nom à la place
        switch (substr ($ligne_url, 0, 2))
        {
            case 84: $nom_reg = "Auvergne-Rhône-Alpes";
                     break;

            case 27: $nom_reg = "Bourgogne-Franche-Comté";
                     break;

            (...)

            case 93: $nom_reg = "Provence-Alpes-Côte d’Azur";
                     break;

            // le cas par défaut ne devrait jamais se produire
            default: $nom_reg = "code ".$args [0];
        }

        // fabriquer la ligne qui sera mémorisée dans le fichier
        $ligne_url = $nom_reg.substr (selchamps_jour ($ligne_url, $doses), 2);

        // la mémoriser
        array_push ($tabligne_reg, $ligne_url);

        // lire la ligne suivante de l'url
        $ligne_url = fgets ($descurl, LG_MAX_CSV);
    }
      
Il ne reste plus qu'à trier le tableau et à remplir le fichier avec son contenu.
    // tri du tableau par ordre alphabétique des noms
    sort ($tabligne_reg);

    // création du fichier csv local
    // pour l'instant, le nom est provisoire
    $nouvcsv = DIR_CSV."/vacsi-tot-reg.new";

    // ouvrir ce fichier en écriture
    $descscv = fopen ($nouvcsv, "w");

    // si l'ouverture s'est bien passée
    if ($descscv)
    {
        // recopier la date dans la première ligne
        fputs ($descscv, $date_url."\n");

        // compléter avec les informations des différentes régions
        for ($i = 0; $i < count ($tabligne_reg); $i++)
            fputs ($descscv, $tabligne_reg [$i]);

        // remplissage fichier terminé
        fclose ($descscv);

        // on remplace l'ancien fichier par le nouveau
        rename ($nouvcsv, $csvreg);
    }
    // sinon
    else
        // message d'erreur si on n'a pas pu créer le fichier
        echo "Problème pour créer le fichier ".basename ($csvreg)."<br>\n";
      

Le fichier vacsi-tot-dom (vaccination par DOM)

Pour les DOM, on utilise le même fichier de référence que pour les régions. Un script spécifique permet de mettre à jour le fichier vacsi-tot-dom.csv. Ce script fonctionne presque comme celui pour les régions.

Toutefois, comme les numéros de DOM se suivent (numérotés de 01 à 08 dans le fichier de référence), on utilise un tableau dont l'indice correspond au code du DOM pour remplacer ce code par le nom du DOM.
      

Le fichier vacsi-totgen-fra

Ce fichier n'est pas obtenu en récupérant sur internet un fichier de référence, mais à partir du fichier local vacsi-tot-a-fra.csv .

En utilisant ce fichier local qui mémorise les taux de vaccination pour les différentes classes d'âge, on va calculer les taux de vaccination à partir d'un certain âge.

Le fichier vacsi-totgen.csv est à jour si sa date de dernière modification est égale à la seconde près ou plus récente que celle du fichier vacsi-tot-a-fra.csv

Pour le vérifier, on utilise la fonction filemtime (...) et si le fichier est déjà à jour, on n'a rien à faire.
    // fichier de référence et fichier à mettre à jour
    $ficref = DIR_CSV."/vacsi-tot-a-fra.csv";
    $ficout = DIR_CSV."/vacsi-totgen-fra.csv";

    // si le fichier de référence n'est pas plus récent que celui à mettre à jour
    if (filemtime ($ficref) <= filemtime ($ficout))
        // on n'a rien à faire
        return;
      
Dans le cas contraire, on va générer un fichier de cette forme :
2023-07-10
0;67863570;54677681-80.6;53773279-79.2;41042237-60.5;10230314-15.1;8591767-12.7
12;58572452;54360406-92.8;53514031-91.4;41029915-70;10229964-17.5;8589496-14.7
18;53442768;50068548-93.7;49350252-92.3;40077208-75;10206373-19.1;8540857-16
40;35884147;33305641-92.8;32952737-91.8;28648415-79.8;9751875-27.2;8164584-22.8
60;18423567;16886637-91.7;16720061-90.8;15318187-83.1;8135592-44.2;6861304-37.2
      
Il ressemble beaucoup au fichier vacsi-tot-a-fra.csv avec des classes d'âge en moins, mais si on regarde les valeur des 4 premiers champs (population et nombre des différentes vaccinations), on constate que ces nombres décroissent lorsqu'on passe à un âge minimal supérieur.
    // fichier de référence et fichier à mettre à jour
    $ficref = DIR_CSV."/vacsi-tot-a-fra.csv";
    $ficout = DIR_CSV."/vacsi-totgen-fra.csv";

    // si le fichier de référence n'est pas plus récent que celui à mettre à jour
    if (filemtime ($ficref) <= filemtime ($ficout))
        // on n'a rien à faire
        return;
      
Pour commencer, après avoir lu et recopié la date du fichier vacsi-tot-a-fra.csv
    // recopier la première ligne du fichier de référence (date)
    fputs ($descout, fgets ($descref, LG_MAX_CSV));
      
on mémorise dans un tableau les autres lignes qu'il contient.
    // on va mémoriser les autres lignes de ce fichier dans l'ordre inverse
    $tabligne = array ();

    // lire la ligne suivante
    $ligne = fgets ($descref, LG_MAX_CSV);

    // tant que non fin de fichier
    while ($ligne)
    {
        // mémoriser la ligne lue en début de liste
        array_unshift ($tabligne, $ligne);

        // lire la ligne suivante
        $ligne = fgets ($descref, LG_MAX_CSV);
    }
      
On peut remarquer, que pour mémoriser ces lignes, on a utilisé la fonction array_unshift (...) au lieu de array_push (...) ce qui a pour conséquence de mémoriser les informations dans l'ordre inverse, c'est à dire les classe d'âge les plus élevées d'abord.

La dernière ligne du fichier vacsi-tot-a-fra.csv contient les informations sur la vaccination toutes classes d'âge confondues. On peut recopier directement cette ligne (qui est au début du tableau) dans le nouveau fichier.
    // le premier élément peut directement être recopié dans le fichier à créer
    fputs ($descout, $tabligne [0]);
      
Ensuite, après avoir initialisé des compteurs pour la population et les différentes doses de vaccination, on parcourt les différentes classes d'âge dans l'ordre où elles apparaissent (des plus âgées aux plus jeunes) en additionnant les populations et nombre de doses de vaccin.

Pour certaines de ces classes d'âge, on calcule aussi les taux de vaccination et on mémorise toutes ces informations dans un nouveau tableau, toujours avec la fonction array_unshift (...) afin de revenir sur un ordre croissant de la liste des âges minimum.
    // nombre d'éléments récoltés
    $nb_elem = count ($tabligne);

    // initialisation des compteurs de population
    $pop_totale = 0;

    for ($i = 0; $i < $doses; $i ++)
        $pop_dose [$i]  = 0;

    // on va mémoriser les totaux pour plusieurs classes d'age dans un autre tableau
    $tabligtot = array ();

    // parcours de la suite des données mémorisées
    for ($j = 1; $j < $nb_elem; $j ++)
    {
        // séparer le champs d'une ligne de données
        $args = explode (";", $tabligne [$j], 10);

        // âge minimal déjà mémorisé dans les totaux de population
        $agemin = $args [0] + 1;

        // pour certains âges minimum
        switch ($agemin)
        {
            case 12 :
            case 18 :
            case 40 :
            case 60 : // fabriquer une ligne du fichier résultat

                      // classse d'âge et population totale
                      $ligne = $agemin.";".$pop_totale;

                      // nombre de doses injectées
                      for ($i = 0; $i < $doses; $i ++)
                          $ligne = $ligne.";".$pop_dose [$i];

                      // calculer et rajouter les pourcentages
                      for ($i = 0; $i < $doses; $i ++)
                      {
                          $taux_dose [$i] = round (($pop_dose [$i]."00") / $pop_totale, 1);
                          $ligne = $ligne.";".$taux_dose [$i];
                      }

                      // fin de la ligne
                      $ligne = $ligne."\n";

                      // rajouter la ligne au début du tableau des totaux
                      array_unshift ($tabligtot, $ligne);

            default : // ne rien faire pour les classes d'âge intermédiaires
                      break;
        }

        // rajouter la population pour la classe d'âge à celle des classes d'âge supérieures
        $pop_totale = $pop_totale + $args [1];

        for ($i = 0; $i < $doses; $i ++)
            $pop_dose [$i] = $pop_dose [$i] + $args [$i + 2];
    }
      
Pour finir, il ne reste plus qu'à recopier les lignes du 2ème tableau dans le fichier vacsi-totgen.csv
    // compléter le fichier avec les sommes de classes d'âge calculées
    foreach ($tabligtot as $ligne_csv)
        fputs ($descout, $ligne_csv);