%%%
% Statistiques
%%%
\def\filedateStat{2026/01/11}%
\def\fileversionStat{0.1d}%
\message{-- \filedateStat\space v\fileversionStat}%
%
\newcommand\NbDonnees{}%
\newcommand\SommeDonnees{}%
\newcommand\EffectifTotal{}%
\newcommand\Moyenne{}%
\newcommand\Etendue{}%
\newcommand\Mediane{}%
\newcommand\DonneeMax{}%
\newcommand\DonneeMin{}%
\newcommand\EffectifMax{}%
\newcommand\PfCArticleMediane{la}%

\setKVdefault[ClesStat]{ColVide=0,CaseVide=false,EffVide=false,%
FreqVide=false,AngVide=false,ECCVide=false,TotalVide=false,Sondage=false,Liste=false,%
Tableau=false,TabVertical=false,Stretch=1,Frequence=false,EffectifTotal=false,%
Etendue=false,Moyenne=false,MVerticale=false,CouleurSol=black,SET=false,ValeurExacte=false,MoyenneA,Somme,Mediane=false,DetailsMediane=false,UneMediane=false,SansRangement=false,QuartileUn=false,QuartileTrois=false,Total=false,%
Largeur=1cm,Precision=2,PrecisionF=0,Donnee=Valeurs,Effectif=Effectif,Grille=false,Origine=0,Angle=false,SemiAngle=false,Qualitatif=false,Classes=false,TableauVide=false,ECC=false,Coupure=10,CouleurTab=gray!15,Graphique=false,Batons=true,Centre=false,CentreVide=false,Crochets=false,Ordre={},%
% Pour les diags batons
EpaisseurBatons=1,ListeCouleursB={a},%BatonVide=false,
Lecture=false,LectureFine=false,AideLecture=false,Reponses=false,DonneesSup=false,%
Tiret=false,Pasx=1,Pasy=1,Unitex=0.5,Unitey=0.5,Depart=0,CouleurDefaut=black,Date=false,GrandNombrey=false,GrandNombrex=false,PasGrillex=1,PasGrilley=1,Relie=false,Codes=false,Pointe=false,%
% Pour les diags circulaires
Rayon=3cm,AffichageAngle=false,AffichagePourcent=false,AffichageDonnee=false,ListeCouleurs={white},Hachures=false,ListeHachures={60},LectureInverse=false,EcartHachures=0.25,EpaisseurHachures=1,Legende,LegendeVide=false,ACompleter=false,DebutAngle=0,%on utilisera également la clé CouleurDefaut
%Pour les représentations
Representation=false,%
%Pour les barres horizontales
Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false,EcartBarre=0,AngleAbsBarre=0,%Grille est dispo
% Pour les histogrammes
Histogramme=false,UniteAire=1,MemeAmpli,DepartHisto=1,%
% Pour la moustache
Moustache=false,Vide=false,IQR=false,Vertical=false,AvecMoyenne=false,Cours=false,Aberration={},%Grille,Pasx,Lecture.
% Pour la quadri...
ModeleCouleur=5,%
% Pour le multi
Multi=false,%
% Pour le Nuage
Nuage=false,PasGradx=1,PasGrady=1,Titre=false,%
% Pour les defKV
Unite={},%
AngleRotationAbscisse={},%
AffichageDonnees={},%
CasesVides={},%
LegendesVides={},%
BatonsVides={},%
GrandNombreO={},%
GrandNombreA={},%
Traces={}%
}%
% compl\'ements
\defKV[ClesStat]{%
  AffichageDonnees=\ifempty{#1}{}{\setKV[ClesStat]{AffichageDonnee}},%
  CasesVides=\ifempty{#1}{}{\setKV[ClesStat]{CaseVide}},%
  LegendesVides=\ifempty{#1}{}{\setKV[ClesStat]{LegendeVide}},%
  GrandNombreO=\ifempty{#1}{}{\setKV[ClesStat]{GrandNombrey}},%
  GrandNombreA=\ifempty{#1}{}{\setKV[ClesStat]{GrandNombrex}},%
  Traces=\ifempty{#1}{}{\setKV[ClesStat]{Codes}}%
}%
% La construction du tableau
\def\addtotok#1#2{#1\expandafter{\the#1#2}}%
\newtoks\tabtoksa\newtoks\tabtoksb\newtoks\tabtoksc%
\def\updatetoks#1/#2\nil{\addtotok\tabtoksa{\ifboolKV[ClesStat]{Qualitatif}{&#1}{&\num{#1}}}\addtotok\tabtoksb{&\num{#2}}}%
%
\newcounter{PfCCompteLignes}%
%
\def\BuildtabStat{% %%Tableau sans/avec total
  \setcounter{PfCCompteLignes}{0}%
  \tabtoksa{\useKV[ClesStat]{Donnee}}\tabtoksb{\useKV[ClesStat]{Effectif}}%
  \foreachitem\compteur\in\ListeComplete{\expandafter\updatetoks\compteur\nil}%
  \renewcommand{\arraystretch}{\useKV[ClesStat]{Stretch}}%
  \ifboolKV[ClesStat]{Total}{%
    \begin{NiceTabular}{c*{\fpeval{\ListeCompletelen+1}}{>{\centering\arraybackslash}p{\useKV[ClesStat]{Largeur}}}}%
      \CodeBefore%
      \rowcolor{\useKV[ClesStat]{CouleurTab}}{1}%
      \columncolor{\useKV[ClesStat]{CouleurTab}}{1}%
      \Body%
      \the\tabtoksa&Total\\%
      \ifboolKV[ClesStat]{EffVide}{\useKV[ClesStat]{Effectif}\xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{&}}{\the\tabtoksb&\num{\EffectifTotal}}\\%
      \ifboolKV[ClesStat]{Frequence}{\stepcounter{PfCCompteLignes}Fr\'equence (\%)\xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{FreqVide}{}{\num{\CalculFrequence{##1}}}}}&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{FreqVide}{}{100}}\\}{}%
      \ifboolKV[ClesStat]{Angle}{\stepcounter{PfCCompteLignes}Angle (\si{\degree})\xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{AngVide}{}{\CalculAngle{##1}}}}&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{AngVide}{}{360}}\\}{}%
      \ifboolKV[ClesStat]{SemiAngle}{\stepcounter{PfCCompteLignes}Angle (\si{\degree})\xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{AngVide}{}{\CalculSemiAngle{##1}}}}&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{AngVide}{}{180}}\\}{}%
      \ifboolKV[ClesStat]{ECC}{\stepcounter{PfCCompteLignes}E.C.C.\xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{ECCVide}{}{\CalculECC{##1}}}}&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{ECCVide}{}{\num{\EffectifTotal}}}\\}{}%
      \CodeAfter%
      % On crée la liste des colonnes à vider
      \xintifboolexpr{\useKV[ClesStat]{ColVide}>0}{%
        \xdef\FooStat{\useKV[ClesStat]{ColVide}}%
        \setsepchar{,}%
        \readlist*\ListeColonnesAVider{\FooStat}%
        \foreachitem\compteur\in\ListeColonnesAVider{%
          \tikz\fill[white] (row-2-|col-\fpeval{\compteur+1}) rectangle (last-|col-\fpeval{\compteur+2});%
        }%
      }{}%
      % On crée la liste des cases à vider
      \ifboolKV[ClesStat]{CaseVide}{%
        \xdef\FooStatCases{\useKV[ClesStat]{CasesVides}}%
        \setsepchar[*]{,*/}%
        \readlist*\ListeCasesAVider{\FooStatCases}%
        \foreachitem\compteur\in\ListeCasesAVider{%
          \tikz\fill[white] (row-\fpeval{\ListeCasesAVider[\compteurcnt,1]+1}-|col-\fpeval{\ListeCasesAVider[\compteurcnt,2]+1}) rectangle (row-\fpeval{\ListeCasesAVider[\compteurcnt,1]+2}-|col-\fpeval{\ListeCasesAVider[\compteurcnt,2]+2});%
        }%
      }{}%
      % On retrace le tableau
      %Les colonnes
      \xintFor* ##1 in {\xintSeq{1}{\fpeval{\ListeCompletelen+3}}}\do{%
        \tikz\draw (row-1-|col-##1) -- (last-|col-##1);%
      }%
      % Les lignes
      \xintFor* ##1 in {\xintSeq{1}{\fpeval{\thePfCCompteLignes+3}}}\do{%
        \tikz\draw (row-##1-|col-1) -- (row-##1-|last);%
      }%
    \end{NiceTabular}%
  }{%
    \begin{NiceTabular}{c*{\fpeval{\ListeCompletelen}}{>{\centering\arraybackslash}p{\useKV[ClesStat]{Largeur}}}}%
      \CodeBefore%
      \rowcolor{\useKV[ClesStat]{CouleurTab}}{1}%
      \columncolor{\useKV[ClesStat]{CouleurTab}}{1}%
      \Body%
      \the\tabtoksa\\%
      \ifboolKV[ClesStat]{EffVide}{\useKV[ClesStat]{Effectif}\xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{&}}{\the\tabtoksb}\\%
      \ifboolKV[ClesStat]{Frequence}{\stepcounter{PfCCompteLignes}Fr\'equence (\%)\xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{FreqVide}{}{\num{\CalculFrequence{##1}}}}}\\}{}%
      \ifboolKV[ClesStat]{Angle}{\stepcounter{PfCCompteLignes}Angle (\si{\degree})\xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{AngVide}{}{\CalculAngle{##1}}}}\\}{}%
      \ifboolKV[ClesStat]{SemiAngle}{\stepcounter{PfCCompteLignes}Angle (\si{\degree})\xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{AngVide}{}{\CalculSemiAngle{##1}}}}\\}{}%
      \ifboolKV[ClesStat]{ECC}{\stepcounter{PfCCompteLignes}E.C.C.\xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{ECCVide}{}{\CalculECC{##1}}}}\\}{}%
      \CodeAfter%
      % On crée la liste des colonnes à vider
      \xintifboolexpr{\useKV[ClesStat]{ColVide}>0}{%
        \xdef\FooStat{\useKV[ClesStat]{ColVide}}%
        \setsepchar{,}%
        \readlist*\ListeColonnesAVider{\FooStat}%
        \foreachitem\compteur\in\ListeColonnesAVider{%
          \tikz\fill[white] (row-2-|col-\fpeval{\compteur+1}) rectangle (last-|col-\fpeval{\compteur+2});%
        }%
      }{}%
      % On crée la liste des cases à vider
      \ifboolKV[ClesStat]{CaseVide}{%
        \xdef\FooStatCases{\useKV[ClesStat]{CasesVides}}%
        \setsepchar[*]{,*/}%
        \readlist*\ListeCasesAVider{\FooStatCases}%
        \foreachitem\compteur\in\ListeCasesAVider{%
          \tikz\fill[white] (row-\fpeval{\ListeCasesAVider[\compteurcnt,1]+1}-|col-\fpeval{\ListeCasesAVider[\compteurcnt,2]+1}) rectangle (row-\fpeval{\ListeCasesAVider[\compteurcnt,1]+2}-|col-\fpeval{\ListeCasesAVider[\compteurcnt,2]+2});%
        }%
      }{}%
      % On retrace le tableau
      %Les colonnes
      \xintFor* ##1 in {\xintSeq{1}{\fpeval{\ListeCompletelen+2}}}\do{%
        \tikz\draw (row-1-|col-##1) -- (last-|col-##1);%
      }%
      % Les lignes
      \xintFor* ##1 in {\xintSeq{1}{\fpeval{\thePfCCompteLignes+3}}}\do{%
        \tikz\draw (row-##1-|col-1) -- (row-##1-|last);%
      }%
    \end{NiceTabular}%
  }%
}%

\def\BuildtabStatVertical{%
  \setcounter{PfCCompteLignes}{2}%Utiliser pour les colonnes, ici.
  \ifboolKV[ClesStat]{Frequence}{\stepcounter{PfCCompteLignes}}{}%
  \ifboolKV[ClesStat]{Angle}{\stepcounter{PfCCompteLignes}}{}%
  \ifboolKV[ClesStat]{SemiAngle}{\stepcounter{PfCCompteLignes}}{}%
  \ifboolKV[ClesStat]{ECC}{\stepcounter{PfCCompteLignes}}{}%
  \begin{NiceTabular}{*{\thePfCCompteLignes}{>{\centering\arraybackslash}p{\useKV[ClesStat]{Largeur}}}}%
    \rowcolor{gray!15}\useKV[ClesStat]{Donnee}&\useKV[ClesStat]{Effectif}%
    \xintifboolexpr{\thePfCCompteLignes>2}{%
      \ifboolKV[ClesStat]{Frequence}{&Fréquence (\%)}{}%
      \ifboolKV[ClesStat]{Angle}{&Angle (\si{\degree})}{}%
      \ifboolKV[ClesStat]{SemiAngle}{&Angle (\si{\degree})}{}%
      \ifboolKV[ClesStat]{ECC}{&E.C.C.}{}%
    }{}%
    \\%
    \xintFor* ##1 in{\xintSeq{1}{\ListeCompletelen}}\do{%
      \ifboolKV[ClesStat]{Qualitatif}{\ListeComplete[##1,1]}{\num{\ListeComplete[##1,1]}}
        \uppercase{&}\num{\ListeComplete[##1,2]}%
      \ifboolKV[ClesStat]{Frequence}{\uppercase{&}%
        \ifboolKV[ClesStat]{TableauVide}{}{%
          \ifboolKV[ClesStat]{FreqVide}{}{%
            \num{\CalculFrequence{##1}}%
          }%
        }%
      }{}%
      \ifboolKV[ClesStat]{Angle}{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{AngVide}{}{\CalculAngle{##1}}}}{}%
      \ifboolKV[ClesStat]{SemiAngle}{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{AngVide}{}{\CalculSemiAngle{##1}}}}{}%
      \ifboolKV[ClesStat]{ECC}{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{ECCVide}{}{\CalculECC{##1}}}}{}%
      \\%
    }%
    \ifboolKV[ClesStat]{Total}{%
      Total&\ifboolKV[ClesStat]{TotalVide}{}{\num{\EffectifTotal}%
      \ifboolKV[ClesStat]{Frequence}{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{FreqVide}{}{100}}}{}%
      \ifboolKV[ClesStat]{Angle}{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{AngVide}{}{360}}}{}%
      \ifboolKV[ClesStat]{SemiAngle}{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{AngVide}{}{180}}}{}%
            \ifboolKV[ClesStat]{ECC}{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{ECCVide}{}{\num{\EffectifTotal}}}}{}%
                  }
      \\        
    }{}%
    \CodeAfter%
    % On crée la liste des « colonnes » à vider
    \xintifboolexpr{\useKV[ClesStat]{ColVide}>0}{%
      \edef\FooStat{\useKV[ClesStat]{ColVide}}%
      \setsepchar{,}%
      \readlist*\ListeColonnesAVider{\FooStat}%
      \foreachitem\compteur\in\ListeColonnesAVider{%
        \tikz\fill[white] (row-\fpeval{\compteur}-|col-2) rectangle (row-\fpeval{\compteur+1} -|last);%
      }%
    }{}%
%    % On crée la liste des cases à vider
    \ifboolKV[ClesStat]{CaseVide}{%
      \edef\FooStatCases{\useKV[ClesStat]{CasesVides}}%
      \setsepchar[*]{,*/}%
      \readlist*\ListeCasesAVider{\FooStatCases}%
      \foreachitem\compteur\in\ListeCasesAVider{%
        \tikz\fill[white] (row-\fpeval{\ListeCasesAVider[\compteurcnt,2]+1}-|col-\fpeval{\ListeCasesAVider[\compteurcnt,1]+1}) rectangle (row-\fpeval{\ListeCasesAVider[\compteurcnt,2]+2}-|col-\fpeval{\ListeCasesAVider[\compteurcnt,1]+2});%
      }%
    }{}%
    % On retrace le tableau
    % Les lignes
    \ifboolKV[ClesStat]{Total}{%
      \xintFor* ##1 in {\xintSeq{1}{\fpeval{\ListeCompletelen+3}}}\do{%
        \tikz\draw (row-##1-|col-1) -- (row-##1-|last);%
      }%
    }{%
      \xintFor* ##1 in {\xintSeq{1}{\fpeval{\ListeCompletelen+2}}}\do{%
        \tikz\draw (row-##1-|col-1) -- (row-##1-|last);%
      }%
    }%
    % Les colonnes
    \xintFor* ##1 in {\xintSeq{1}{\fpeval{\thePfCCompteLignes+1}}}\do{%
      \tikz\draw (row-1-|col-##1) -- (last-|col-##1);%
    }%
  \end{NiceTabular}%
}%

% Pour construire le diagramme en barres horizontales
\def\UpdatetoksHor#1/#2/#3\nil{\addtotok\toklistenomhor{"#1",}\addtotok\toklistedonhor{#3,}\addtotok\toklisteaffhor{"#2",}}%

\newcommand\buildgraphbarhor{%
  \newtoks\toklistenomhor%
  \newtoks\toklistedonhor%
  \newtoks\toklisteaffhor%
  % \newtoks\toklistecouleur%
  \toklistecouleur{}%
  \edef\PfCfooStat{}%
  \xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{%
    \edef\PfCfooStat{\PfCfooStat \ListeComplete[##1,2],}%
  }%
  \edef\DivMax{\fpeval{max(\PfCfooStat)}}%
  \edef\ExposantDivMax{\fpeval{round(ln(\DivMax)/ln(10))}}%
  \edef\DivMax{\fpeval{10**\ExposantDivMax}}%
  \edef\PfCfooStat{}%
  \xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{%
    \edef\PfCfooStat{\PfCfooStat \ListeComplete[##1,1]/\ListeComplete[##1,2]/\fpeval{\ListeComplete[##1,2]/\DivMax},}%
  }%
  \edef\ListeAvantCouleurs{\useKV[ClesStat]{ListeCouleurs}}%
  \setsepchar[*]{,*/}\ignoreemptyitems%
  \readlist*\ListeCompleteDiagHor{\PfCfooStat}%
  \readlist*\ListeCouleur{\ListeAvantCouleurs}%
  \reademptyitems%
  \foreachitem\compteur\in\ListeCompleteDiagHor{\expandafter\UpdatetoksHor\compteur\nil}%
  \foreachitem\couleur\in\ListeCouleur{\expandafter\UpdateCoul\couleur\nil}%
  \NewMPDiagBarreHor{\the\toklistenomhor}{\the\toklistedonhor}{\the\toklisteaffhor}{\the\toklistecouleur}%
}%

% Pour construire le diagramme en bâtons
\def\Updatetoks#1/#2\nil{\addtotok\toklistepoint{(#1,#2),}}%
\newtoks\toklistepoint
\newtoks\toklistecouleur
\newtoks\toklistelegende

\newcommand\buildgraph[1][]{%
  \toklistepoint{}%
  \toklistecouleur{}%
  \toklistelegende{}%
  \ifboolKV[ClesStat]{LegendeVide}{%
    \xdef\foo{\useKV[ClesStat]{LegendesVides}}%
    \readlist*\ListeLegendesAEffacer{\foo}%
  }{\xdef\foo{-1}\readlist*\ListeLegendesAEffacer{\foo}%
  }%
  \foreachitem\compteur\in\ListeLegendesAEffacer{\expandafter\UpdateLegende\compteur\nil}%
  \foreachitem\compteur\in\ListeComplete{\expandafter\Updatetoks\compteur\nil}%
  \xdef\ListeAvantCouleurs{\useKV[ClesStat]{ListeCouleursB}}%
  \readlist*\ListeCouleur{\ListeAvantCouleurs}%
  \foreachitem\couleur\in\ListeCouleur{\expandafter\UpdateCoul\couleur\nil}%
  \MPStatNew{\the\toklistepoint}{\the\toklistecouleur}{\the\toklistelegende}
}%

% Pour construire le diagramme en bâtons qualitatif
\def\Updatetoksq#1/#2\nil{\addtotok\toklistepointq{"#1",#2,}}%
\newcommand\buildgraphq[1][]{%
  \newtoks\toklistepointq\toklistepointq{}%
  % \newtoks\toklistecouleur
  \toklistecouleur{}%
  \newtoks\toklistelegende\toklistelegende{}%
  \ifboolKV[ClesStat]{LegendeVide}{%
    \xdef\foo{\useKV[ClesStat]{LegendesVides}}%
  }{%
    \xdef\foo{-1}%
  }%
  \setsepchar{,}\ignoreemptyitems%
  \readlist*\ListeLegendesAEffacer{\foo}%
  \reademptyitems%
  \foreachitem\compteur\in\ListeLegendesAEffacer{\expandafter\UpdateLegende\compteur\nil}%
  \foreachitem\compteur\in\ListeComplete{\expandafter\Updatetoksq\compteur\nil}%
  \xdef\ListeAvantCouleurs{\useKV[ClesStat]{ListeCouleursB}}%
  \readlist*\ListeCouleur{\ListeAvantCouleurs}%
  \foreachitem\couleur\in\ListeCouleur{\expandafter\UpdateCoul\couleur\nil}%
  %\edef\RetiensListePoint{\the\toklistepointq}%
  \MPStatNew{\the\toklistepointq}{\the\toklistecouleur}{\the\toklistelegende}%
}%

\def\UpdateCoul#1\nil{\addtotok\toklistecouleur{#1,}}%
\def\UpdateHach#1\nil{\addtotok\toklisteanglehachure{#1,}}%
\def\UpdateLegende#1\nil{\addtotok\toklistelegende{#1,}}%
\def\UpdateBatons#1\nil{\addtotok\toklistebatonsvides{#1,}}%

% Pour construire le diagramme circulaire qualitatif
\def\buildgraphcq#1{%
  \newtoks\toklistepointq\toklistepointq{}%
  % \newtoks\toklistecouleur
  \toklistecouleur{}%
  \newtoks\toklisteanglehachure\toklisteanglehachure{}%
  \newtoks\toklistelegende\toklistelegende{}%
  \ifboolKV[ClesStat]{LegendeVide}{%
    \xdef\foo{\useKV[ClesStat]{LegendesVides}}%
    \readlist*\ListeLegendesAEffacer{\foo}%
  }{\xdef\foo{0}\readlist*\ListeLegendesAEffacer{\foo}%
  }%
  \foreachitem\compteur\in\ListeLegendesAEffacer{\expandafter\UpdateLegende\compteur\nil}%
  %
  \foreachitem\compteur\in\ListeComplete{\expandafter\Updatetoksq\compteur\nil}%
  \xdef\ListeAvantCouleurs{\useKV[ClesStat]{ListeCouleurs}}%
  \readlist*\ListeCouleur{\ListeAvantCouleurs}%
  \foreachitem\couleur\in\ListeCouleur{\expandafter\UpdateCoul\couleur\nil}%
  \xdef\ListeAvantHachures{\useKV[ClesStat]{ListeHachures}}%
  \readlist*\ListeHachure{\ListeAvantHachures}%
  \foreachitem\valeurangle\in\ListeHachure{\expandafter\UpdateHach\valeurangle\nil}%
  \NewMPStatCirculaireQ{\the\toklistepointq}{#1}{\the\toklistecouleur}{\the\toklistelegende}{\the\toklisteanglehachure}%
}%

%% calcul des fr\'equences
\newcommand\CalculFrequence[1]{%
  \fpeval{round(\ListeComplete[#1,2]*100/\EffectifTotal,\useKV[ClesStat]{PrecisionF})}
}

%% calcul des angles
\newcommand\CalculAngle[1]{%
  \fpeval{round(\ListeComplete[#1,2]*360/\EffectifTotal,0)}
}
\newcommand\CalculSemiAngle[1]{%
  \fpeval{round(\ListeComplete[#1,2]*180/\EffectifTotal,0)}
}

%% calcul des ECC
\newcount\CompteurECC%
\newcount\CompteurECCTotal%
\newcount\CompteurECCC%
\newcount\CompteurECCCTotal%

\newcommand\CalculECC[1]{%
  \xdef\TotalECC{0}%
  \CompteurECC=1%
  \CompteurECCTotal=\numexpr#1+1%
  \whiledo{\CompteurECC < \CompteurECCTotal}{%
    \xdef\TotalECC{\fpeval{\TotalECC+\ListeComplete[\the\CompteurECC,2]}}%
    \CompteurECC=\numexpr\CompteurECC+1%
  }%
  \num{\TotalECC}%
}

\def\NewMPDiagBarreHorCode{%
  Longueur:=\useKV[ClesStat]{Longueur};
  Hauteur:=\useKV[ClesStat]{Hauteur};
  Ecart:=\useKV[ClesStat]{EcartBarre};
  ExposantDivMax:=\ExposantDivMax;
  ecarthachures=\useKV[ClesStat]{EcartHachures};
  epaisseurhachures=\useKV[ClesStat]{EpaisseurHachures};
  AngleAbsBarre:=\useKV[ClesStat]{AngleAbsBarre};
  boolean Hachures,Bicolore,Grille,AffichageDonnee,LegendeVide;
  Hachures=\useKV[ClesStat]{Hachures};
  Bicolore=\useKV[ClesStat]{Bicolore};
  Grille=\useKV[ClesStat]{Grille};
  AffichageDonnee=\useKV[ClesStat]{AffichageDonnee};
  LegendeVide=\useKV[ClesStat]{LegendeVide};
  vardef CalculNombreDonneesEtDonneeMax(text t)=
  nbdon:=0;%nombre de données
  DonneeMax:=0;%donnée DonneeMaximale
  for p_=t:
  nbdon:=nbdon+1;
  if p_>DonneeMax:
  DonneeMax:=p_;
  fi;
  endfor;
  enddef;
  vardef ListeDonnees(text t)=
  n:=0;
  for p_=t:
  n:=n+1;
  Donnees[n]:=p_;
  endfor;
  enddef;
  vardef RecuperationCouleurs(text t)=
  color Col[];
  n:=0;
  for p_=t:
  n:=n+1;
  Col[n]=p_;
  endfor;
  enddef;
}

% Construction d'un diagramme en barres horizontal
\newcommand\NewMPDiagBarreHor[4]{%
  % #1 Liste des noms
  % #2 Liste des valeurs associées
  % #3 Liste des valeurs à afficher (si pb calcul MP)
  % #4 Liste des couleurs
  \mplibforcehmode%
  \begin{mplibcode}%
    defaultcolormodel := \useKV[ClesStat]{ModeleCouleur};
    \NewMPDiagBarreHorCode%
    vardef TraceDiag=
    if Grille:
    pair Zz[];%Pour déterminer "le dernier point"
    Zz0=(0,-(nbdon-1)*(Hauteur+Ecart)-Ecart);
    Zz2=(0,(Hauteur+Ecart));
    Zz1=((1/DonneeMax)*Longueur,-(nbdon-1)*(Hauteur+Ecart)-Ecart);
    Zz3=if ExposantDivMax=0 : (DonneeMax+1)[Zz0,Zz1] else: ((floor(DonneeMax*10+2))/10)[Zz0,Zz1];fi;
    if ExposantDivMax=0:
    for k=1 upto DonneeMax+1:
    trace (Zz0--Zz2) shifted (k*(Zz1-Zz0)) dashed evenly withcolor 0.5white;
    endfor;
    else:
    for k=1 upto (floor(DonneeMax*10+2)):
    trace (Zz0--Zz2) shifted ((k/10)*(Zz1-Zz0)) dashed evenly withcolor 0.5white;
    endfor;
    fi;
    if ExposantDivMax=0:
    for k=1 upto (DonneeMax+1):
    label.bot(TEX("\num{"&decimal(k)&"}") rotated AngleAbsBarre,Zz0+k*(Zz1-Zz0));
    endfor;
    else:
    if ExposantDivMax<5:
    for k=1 upto (floor(DonneeMax*10+2)):
    label.bot(TEX("\num{\fpeval{"&decimal(k)&"*(10**"&decimal(ExposantDivMax-1)&")}}") rotated AngleAbsBarre,Zz0+(k/10)*(Zz1-Zz0));
    endfor;
    else:
    dotlabel.bot(TEX("\num{\fpeval{10**"&decimal(ExposantDivMax)&"}}") rotated AngleAbsBarre,Zz1);
    fi;
    fi;
    fi;
    for k=0 upto nbdon-1:
    path RectangleDonnee;
    RectangleDonnee=(unitsquare xscaled ((Donnees[k+1]/DonneeMax)*Longueur) yscaled Hauteur) shifted(0,-k*(Hauteur+Ecart));
    if Hachures:
    fill RectangleDonnee withcolor white;
    trace Hachurage(RectangleDonnee,60 if
    (k mod 2)=0: +90 fi,ecarthachures,if (k mod 2)=0 : 0 else: 1 fi)
    withpen pencircle scaled epaisseurhachures;
    else:
    remplis RectangleDonnee withcolor if unknown Col[k+1]: if Bicolore:Col[(k mod 2)+1] else: white fi; else:if Bicolore:Col[(k mod 2)+1] else: Col[k+1] fi; fi;
    fi;
    trace RectangleDonnee;
    endfor;
    if Grille:
    drawarrow (0,-(nbdon-1)*(Hauteur+Ecart)-Ecart)--(0,(Hauteur+Ecart)) withpen pencircle scaled 1.5;
    drawarrow (0,-(nbdon-1)*(Hauteur+Ecart)-Ecart)--(Zz3+u*(0.25,0)) withpen pencircle scaled 1.5;
    fi;
    enddef;
    vardef AffichageNom(text t)=
    k:=0;
    for p_=t:
    label.lft(TEX(p_),0.5[(0,0),(0,Hauteur)] shifted (0,-k*(Hauteur+Ecart)));
    k:=k+1;
    endfor;
    enddef;
    vardef AffichageDonnees(text t)=
    k:=0;
    for p_=t:
    label.rt(TEX("\num{"&p_&"}"),0.5[(0,0),(0,Hauteur)] shifted (((Donnees[k+1]/DonneeMax)*Longueur),-k*(Hauteur+Ecart)));
    k:=k+1;
    endfor;
    enddef;
    CalculNombreDonneesEtDonneeMax(#2);
    ListeDonnees(#2);
    RecuperationCouleurs(#4);
    TraceDiag;
    if LegendeVide=false:
    AffichageNom(#1);
    fi;
    if AffichageDonnee:
    AffichageDonnees(#3);
    fi;
  \end{mplibcode}
}%

\def\MPStatNewCode{%
  maxx:=0;
  maxy:=0;
  unitex:=\useKV[ClesStat]{Unitex}*cm;
  unitey:=\useKV[ClesStat]{Unitey}*cm;
  xpartorigine:=\useKV[ClesStat]{Origine};
  boolean Lecture,LectureFine,AideLecture,DonneesSup,Reponses,Qualitatif,Tiret,LegendeVide,Retour,RetourBaton,GrandNombrex,GrandNombrey,Date,Grille,BatonVide,Relie,Codes,Pointe;
  GrandNombrex=\useKV[ClesStat]{GrandNombrex};
  GrandNombrey=\useKV[ClesStat]{GrandNombrey};
  if GrandNombrex:
    GrandNombreA=\useKV[ClesStat]{GrandNombreA};
  fi;
  if GrandNombrey:
    GrandNombreO=\useKV[ClesStat]{GrandNombreO};
  fi;
  Date:=\useKV[ClesStat]{Date};
  %
  \ifemptyKV[ClesStat]{AngleRotationAbscisse}{AngleRotation=0;}{AngleRotation=\useKV[ClesStat]{AngleRotationAbscisse};}
    %
  Lecture=\useKV[ClesStat]{Lecture};
  LectureFine=\useKV[ClesStat]{LectureFine};
  AideLecture=\useKV[ClesStat]{AideLecture};
  DonneesSup=\useKV[ClesStat]{DonneesSup};
  Reponses=\useKV[ClesStat]{Reponses};
  Relie=\useKV[ClesStat]{Relie};
  Codes=\useKV[ClesStat]{Codes};
  Pointe=\useKV[ClesStat]{Pointe};
  LegendeVide=\useKV[ClesStat]{LegendeVide};
  \ifemptyKV[ClesStat]{BatonsVides}{BatonVide=false;}{BatonVide=true;}%
  epaisseurbatons=\useKV[ClesStat]{EpaisseurBatons};
  Qualitatif=\useKV[ClesStat]{Qualitatif};
  Tiret=\useKV[ClesStat]{Tiret};
  Retour=false;
  RetourBaton=false;
  Grille:=\useKV[ClesStat]{Grille};
  Pasx:=\useKV[ClesStat]{Pasx};
  Pasy:=\useKV[ClesStat]{Pasy};
  PasGrillex:=\useKV[ClesStat]{PasGrillex};
  PasGrilley:=\useKV[ClesStat]{PasGrilley};
  color CoulDefaut;
  CoulDefaut=\useKV[ClesStat]{CouleurDefaut};
  Depart=\useKV[ClesStat]{Depart};
  %
  pair A[],B[],P[];
  vardef toto(text t)=%points quantitatif
  n:=0;
  for p_=t:
  if pair p_:
  n:=n+1;
  P[n]=((xpart(p_)-(xpartorigine))*unitex,(ypart(p_)-Depart)*unitey);
  if xpart(p_)>maxx:
  maxx:=xpart(p_);%-(xpartorigine);
  fi;
  if ypart(p_)>maxy:
  maxy:=ypart(p_);
  fi;
  A[n]=unitex*(xpart(p_)-(xpartorigine),0);
  B[n]=unitey*(0,ypart(p_));
  fi;
  endfor;
  maxx:=maxx-(xpartorigine);
  maxy:=maxy-Depart;
  if DonneesSup:
  maxAxey:=maxy;%floor(maxy/10)*10+4*PasGrilley;
  else:
  maxAxey:=maxy;
  fi;
  enddef;
  vardef tutu(text t)=%points qualitatif
  n:=0;
  for p_=t:
  if numeric p_:
  P[n]=((n)*unitex,unitey*(p_-Depart));
  B[n]=(0,unitey*(p_-Depart));
  if p_>maxy:
  maxy:=p_;
  fi;
  else:
  n:=n+1;
  A[n]=unitex*(n,0);
  fi;
  endfor;
  maxy:=maxy-Depart;
  maxx:=n;
  if DonneesSup:
  maxAxey:=floor(maxy/10)*10+4*PasGrilley;
  else:
  maxAxey:=maxy;
  fi;
  enddef;
}

% Construction du graphique en bâtons
\newcommand\MPStatNew[3]{%
  \mplibforcehmode
  \begin{mplibcode}
    defaultcolormodel := \useKV[ClesStat]{ModeleCouleur};
    %
    \MPStatNewCode
    %
    vardef Test(expr nb)=
    Retour:=false;
    op:=0;
    for l_=#3:
    if l_=nb:
    op:=op+1;
    fi;
    endfor;
    if op>0:
    Retour:=true;
    fi;
    enddef;
    %
    vardef TestBatons(expr nb)=
    RetourBaton:=false;
    op:=0;
    for l_=\useKV[ClesStat]{BatonsVides}:
    if l_=nb:
    op:=op+1;
    fi;
    endfor;
    if op>0:
    RetourBaton:=true;
    fi;
    enddef;
    % on r\'ecup\`ere les couleurs
    color Col[];
    n:=0;
    for p_=#2:
    n:=n+1;
    if color p_:
    Col[n]=p_;
    else:
    Col[n]=CoulDefaut;
    fi;
    endfor;
    vardef tata(text t)=%affichage quantitatif
    l=0;
    for p_=t:
      if pair p_:
        l:=l+1;
        %if Rotation:
          if Date:
            label.bot(TEX(decimal(xpart(p_))) rotated AngleRotation,A[l]);
          else:
            if GrandNombrex:
              label.bot(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreA}*"&decimal(xpart(p_))&"}}") rotated AngleRotation,A[l]);
            else:
              label.bot(TEX("\num{"&decimal(xpart(p_))&"}") rotated AngleRotation,A[l]);
            fi;
          fi;
        %else:
        %  if Date:
        %    label.bot(TEX(decimal(xpart(p_))),A[l]);
        %  else:
        %    if GrandNombrex:
        %    
        %    else:
        %      label.bot(TEX("\num{"&decimal(xpart(p_))&"}"),A[l]);
        %    fi;
        %  fi;
        %fi;
        if Reponses:
          if DonneesSup:
            Test(l);
            if Retour=false:
              if GrandNombrey:
                label.top(TEX("\num{"&decimal(ypart(p_))&"}"),P[l]);
              else:
                label.top(TEX("\num{"&decimal(ypart(p_))&"}"),P[l]);
              fi;
            fi;
          else:
            if Tiret:
              trace (B[l]+(-1pt,0))--(B[l]+(1pt,0));
              label.lft(TEX("\num{"&decimal(p_)&"}"),B[l]);
            else:
              dotlabel.lft(TEX("\num{"&decimal(ypart(p_))&"}"),B[l]);
            fi;
          fi;
        fi;
      fi;
    endfor;
    enddef;
    vardef titi(text t)=%affichage qualitatif
      l:=0;
      for p_=t:
        if numeric p_:
          if Reponses:
            if DonneesSup:
              Test(l);
              if Retour=false:
                label.top(TEX("\num{"&decimal(p_)&"}"),P[l]);
              fi;
            else:
              if Tiret:
                trace (B[l]+(-1pt,0))--(B[l]+(1pt,0));
                label.lft(TEX("\num{"&decimal(p_)&"}"),B[l]);
              else:
                dotlabel.lft(TEX("\num{"&decimal(p_)&"}"),B[l]);
              fi;
            fi;
          fi;
        else:
          l:=l+1;
          %if Rotation:
            if AngleRotation<>0:
              picture TEXTELABEL;
              TEXTELABEL=image(
                labeloffset:=labeloffset*2;
                label.lft(TEX(p_),A[l]);
                labeloffset:=labeloffset/2;
              );
              trace rotation(TEXTELABEL,A[l],AngleRotation);
            else :
              label.bot(TEX(p_),A[l]);
            fi;
          %fi;
        fi;
      endfor;
    enddef;
    if Qualitatif: tutu(#1); else: toto(#1); fi;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if Grille:
      drawoptions(withcolor 0.75white);
      for k=0 step PasGrillex until ((maxx+1)):
        trace (k*unitex,0)--(k*unitex,unitey*((ceiling(maxAxey/Pasy)+1)*Pasy));
      endfor;
      for k=0 step PasGrilley until (ceiling(maxAxey/Pasy)+1)*Pasy:%((maxy+2*Pasy)):
        trace (0,k*unitey)--(unitex*(maxx+1),k*unitey);
      endfor;
      drawoptions();
    fi;
    if epaisseurbatons<>0:
      if Relie:
        for k=2 upto n:
          draw (P[k-1]--P[k]);
        endfor;
      else:
        for k=1 upto n:
          if BatonVide:TestBatons(k);fi;
            if RetourBaton=false:
              fill polygone(A[k]-(epaisseurbatons*1pt,0),A[k]+(epaisseurbatons*1pt,0),P[k]+(epaisseurbatons*1pt,0),P[k]-(epaisseurbatons*1pt,0)) withcolor if unknown Col[k]: CoulDefaut else:Col[k] fi;
              if AideLecture:
              draw B[k]--P[k] dashed evenly;
            fi;
          fi;
        endfor;
      fi;
    fi;
    if LectureFine:
    for k=0 step Pasy until ((maxy+1*Pasy)):
    if Tiret:
    trace (1pt,k*unitey)--(-1pt,k*unitey);
    if GrandNombrey:
    label.lft(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreO}*"&decimal(k+Depart)&"}}"),(0,k*unitey));
    else:
    label.lft(TEX("\num{"&decimal(k+Depart)&"}"),(0,k*unitey));
    fi;
    else:
    if GrandNombrey:
    dotlabel.lft(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreO}*"&decimal(k+Depart)&"}}"),(0,k*unitey));
    else:
    dotlabel.lft(TEX("\num{"&decimal(k+Depart)&"}"),(0,k*unitey));
    fi;
    fi;
    endfor;
    fi;
    if Lecture:
    for k=0 step Pasy until Pasy:
    if Tiret:
    trace (1pt,k*unitey)--(-1pt,k*unitey);
    if GrandNombrey:
    label.lft(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreO}*"&decimal(k+Depart)&"}}"),(0,k*unitey));
    else:
    label.lft(TEX("\num{"&decimal(k+Depart)&"}"),(0,k*unitey));
    fi;
    else:
    if GrandNombrey:
    dotlabel.lft(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreO}*"&decimal(k+Depart)&"}}"),(0,k*unitey));
    else:
    dotlabel.lft(TEX("\num{"&decimal(k+Depart)&"}"),(0,k*unitey));
    fi;
    fi;
    endfor;
    fi;
    drawarrow (0,0)--unitex*(maxx+1,0);
    drawarrow (0,0)--unitey*(0,(ceiling(maxAxey/Pasy)+1)*Pasy);
    %
    if Relie:
      if Pointe:
        for k=1 upto n:
          fill cercles(P[k],0.5mm) withcolor white;
          trace cercles(P[k],0.5mm);
        endfor;
      fi;
    fi;
    label.lrt(TEX("\useKV[ClesStat]{Donnee}"),unitex*(maxx+1,0));
    label.urt(TEX("\useKV[ClesStat]{Effectif}"),unitey*(0,(ceiling(maxAxey/Pasy)+1)*Pasy));
    if Qualitatif: titi(#1); else:tata(#1); fi;
    if Codes:
    \useKV[ClesStat]{Traces};
    fi;
  \end{mplibcode}
}

\def\NewMPStatCirculaireCodeQ{%
  Rayon:=\useKV[ClesStat]{Rayon};
  ecarthachures=\useKV[ClesStat]{EcartHachures};
  epaisseurhachures=\useKV[ClesStat]{EpaisseurHachures};
  boolean AffichageAngle,AffichageDonnee,AffichagePourcent,Hachures,Inverse,Legende,LegendeVide,Retour,ACompleter,Codes,Qualitatif;
  Qualitatif=\useKV[ClesStat]{Qualitatif};
  AffichageAngle=\useKV[ClesStat]{AffichageAngle};
  AffichageDonnee=\useKV[ClesStat]{AffichageDonnee};
  AffichagePourcent=\useKV[ClesStat]{AffichagePourcent};
  Hachures=\useKV[ClesStat]{Hachures};
  Inverse=\useKV[ClesStat]{LectureInverse};
  Legende=\useKV[ClesStat]{Legende};
  LegendeVide=\useKV[ClesStat]{LegendeVide};
  Codes=\useKV[ClesStat]{Codes};
  Retour=false;
  ACompleter=\useKV[ClesStat]{ACompleter};
  DebutAngle=\useKV[ClesStat]{DebutAngle};
  color CoulDefaut;
  CoulDefaut=\useKV[ClesStat]{CouleurDefaut};
  %
  pair A[],O,B[],C[],D[];
  O=(0,0);
  n:=0;
  numeric total[],ang[];
  total[0]=0;
  ang[0]:=0;
  path cc;
  cc=(fullcircle scaled (2*Rayon));
  %
  vardef AfficheLegende(text t)=
  picture ResultatLegende;
  ResultatLegende=image(
  for p_=t:
  if string p_:
  n:=n+1;
  C[n]=A[n-1] rotatedabout(O,if Inverse:-1* fi(ang[n]-ang[n-1])/2);
  draw 0.95[O,C[n]]--1.05[O,C[n]];
  C[n]:=1.05[O,C[n]];
  Test(n);
  if ((xpart(C[n])>xpart(O)) or (xpart(C[n])=xpart(O))) and ((ypart(C[n])>ypart(O)) or (ypart(C[n])=ypart(O))):
  D[n]=C[n]+(0.5cm,0);
  draw C[n]--D[n];
  if Retour=false:if Qualitatif:label.urt(TEX(p_),D[n]); else : label.urt(TEX("\num{"&p_&"}"),D[n]);fi;fi;
  fi;
  if (xpart(C[n])<xpart(O)) and ((ypart(C[n])>ypart(O)) or (ypart(C[n])=ypart(O))):
  D[n]=C[n]-(0.5cm,0);
  draw C[n]--D[n];
  if Retour=false:if Qualitatif:label.ulft(TEX(p_),D[n]); else: label.ulft(TEX("\num{"&p_&"}"),D[n]); fi;fi;
  fi;
  if (xpart(C[n])<xpart(O)) and (ypart(C[n])<ypart(O)):
  D[n]=C[n]-(0.5cm,0);
  draw C[n]--D[n];
  if Retour=false:if Qualitatif:label.llft(TEX(p_),D[n]); else:label.llft(TEX("\num{"&p_&"}"),D[n]); fi;fi;
  fi;
  if ((xpart(C[n])>xpart(O)) or (xpart(C[n])=xpart(O))) and (ypart(C[n])<ypart(O)):
  D[n]=C[n]+(0.5cm,0);
  draw C[n]--D[n];
  if Retour=false:if Qualitatif:label.lrt(TEX(p_),D[n]); else:label.lrt(TEX("\num{"&p_&"}"),D[n]); fi;fi;
  fi;
  fi;
  endfor;
  );
  ResultatLegende
  % fi;
  enddef;
}

% la construction du graphique qualitatif
\def\NewMPStatCirculaireQ#1#2#3#4#5{%
  %#1 : la liste des données
  %#2 : 360 ou 180
  %#3 : liste des couleurs
  %#4 : liste des légendes à effacer.
  %#5 : liste des angles des hachures
    \mplibforcehmode
  \begin{mplibcode}
    defaultcolormodel := \useKV[ClesStat]{ModeleCouleur};
    %
    \NewMPStatCirculaireCodeQ
    if Inverse=false:
    A[0]=(point(0) of cc) rotatedabout(O,DebutAngle);
    else:
    if #2=180:
    A[0]=(point(4) of cc) rotatedabout(O,DebutAngle);
    else:
    A[0]=(point(2) of cc) rotatedabout(O,DebutAngle);
    fi;
    fi;
    % on r\'ecup\`ere les couleurs
    color Col[];
    n:=0;
    for p_=#3:
    n:=n+1;
    % Col[n]=p_;
    if color p_:
    Col[n]=p_;
    else:
    Col[n]=CoulDefaut;
    fi;
    endfor;
    % on r\'ecup\`ere les angles d'hachures
    numeric anglehach[];
    n:=0;
    for p_=#5:
    n:=n+1;
    anglehach[n]=p_;
    endfor;
    vardef toto(text t)=
    n:=0;
    for p_=t:
    if numeric p_:
    n:=n+1;
    total[n]:=total[n-1]+p_;
    fi;
    endfor;
    N=n;
    for k=1 upto N:
    ang[k]=(#2/total[N])*total[k];
    endfor;
    n:=0;
    for p_=t:
    if numeric p_:
    n:=n+1;
    if Inverse=false:
    A[n]=A[n-1] rotatedabout(O,p_*(#2/total[N]));
    else:
    A[n]=A[n-1] rotatedabout(O,-p_*(#2/total[N]));
    fi;
    %hachure ou pas ?
    if Hachures=false:
    fill (O--if Inverse=false:arccercle(A[n-1],A[n],O) else:
    arccercle(A[n],A[n-1],O) fi--cycle) withcolor if unknown Col[n]: white else:Col[n] fi;
    else:
    draw
    Hachurage((O--if Inverse=false:arccercle(A[n-1],A[n],O)
    else:arccercle(A[n],A[n-1],O) fi--cycle),if unknown anglehach[n]:p_*(#2/total[N]) if
    (n mod 2)=0: +90 else: -90 fi else: anglehach[n] fi,ecarthachures,if (n mod 2)=0 : 0 else: 1 fi)
    withpen pencircle scaled epaisseurhachures if AffichageAngle: withcolor 0.5white fi;
    fi;
    if ACompleter=false:
    draw A[n-1]--O--A[n] if Hachures: withpen pencircle scaled2 fi;
    fi;
    % Affichage des angles associ\'es
    if AffichageAngle or AffichageDonnee or AffichagePourcent:
      if round(p_*(#2/total[N]))>15:
        if (n mod 2)=0:
          marque_a:=(20+(total[n] div total[N]))*0.75*Rayon/cm;
        else:
          marque_a:=(20-(total[n] div total[N]))*0.5*Rayon/cm;
        fi;
        if AffichageAngle:
          pv:=round(p_*(#2/total[N]));
          if Hachures:
            if Inverse=false:
              undraw Codeangle(A[n-1],O,A[n],0,(((TEX("\ang{"&decimal(pv)&"}")))));
            else:
              undraw Codeangle(A[n],O,A[n-1],0,(((TEX("\ang{"&decimal(pv)&"}")))));
            fi;
            fill cercles(w shifted(marque_ang*unitvector(w-O)),3mm) withcolor blanc;
          fi;
          if Inverse=false:
            draw Codeangle(A[n-1],O,A[n],0,(((TEX("\ang{"&decimal(pv)&"}")))));
          else:
            draw Codeangle(A[n],O,A[n-1],0,(((TEX("\ang{"&decimal(pv)&"}")))));
          fi;
        elseif AffichageDonnee:
          if Hachures:
            if Inverse=false:
              undraw Codeangle(A[n-1],O,A[n],0,TEX(""&decimal(p_)&""));
            else:
              undraw Codeangle(A[n],O,A[n-1],0,(((TEX(""&decimal(p_)&"")))));
            fi;
            fill cercles(w shifted(marque_ang*unitvector(w-O)),3mm) withcolor blanc;
          fi;
          if Inverse=false:
            draw Codeangle(A[n-1],O,A[n],0,(((TEX(""&decimal(p_)&"")))));
          else:
            draw Codeangle(A[n],O,A[n-1],0,(((TEX(""&decimal(p_)&"")))));
          fi;
        elseif AffichagePourcent:
          pv:=round(100*(p_/total[N]));
          marque_ang:=marque_ang*1.25;
          if Hachures:
            if Inverse=false:
              undraw Codeangle(A[n-1],O,A[n],0,TEX("\SI{"&decimal(pv)&"}{\percent}"));
            else:
              undraw Codeangle(A[n],O,A[n-1],0,(((TEX("\SI{"&decimal(pv)&"}{\percent}")))));
            fi;
            fill cercles(w shifted(marque_ang*unitvector(w-O)),4mm) withcolor blanc;
          fi;
          if Inverse=false:
            draw Codeangle(A[n-1],O,A[n],0,(((TEX("\SI{"&decimal(pv)&"}{\percent}")))));
          else:
            draw Codeangle(A[n],O,A[n-1],0,(((TEX("\SI{"&decimal(pv)&"}{\percent}")))));
          fi;
          marque_ang:=marque_ang/1.25;
        fi;
      fi;
      fi;
      fi;
    endfor;
    if #2=360:
    draw cc if Hachures: withpen pencircle scaled2 fi;
    else:
    draw (subpath(0,length cc/2) of cc)--cycle if Hachures: withpen pencircle scaled2 fi;;
    fi;
    n:=0;
    enddef;
    vardef Test(expr nb)=
    Retour:=false;
    op:=0;
    for l_=#4:
    if l_=nb:
    op:=op+1;
    fi;
    endfor;
    if op>0:
    Retour:=true;
    fi;
    enddef;
    %
    toto(#1);
    if Legende:
    n:=0;
    draw AfficheLegende(#1);
    fi;
    if Codes:
    \useKV[ClesStat]{Traces};
    fi;
  \end{mplibcode}
}%

\ExplSyntaxOn
\fp_new:N \l_medianea_int
\fp_new:N \l_medianeb_int

\NewDocumentCommand\CalculMedianeListe{m}{%
  \clist_set:Ne \l_tmpa_clist {#1}
  \int_set:Nn \l_tmpa_int {\clist_count:N \l_tmpa_clist}
  \ifodd\l_tmpa_int
    \int_set:Nn \l_tmpb_int {\fpeval{ceil(\l_tmpa_int/2)}}
    \fp_set:Nn \l_medianea_int {\clist_item:Nn \l_tmpa_clist {\l_tmpb_int}}
    \xdef\Mediane{\fpeval{\l_medianea_int}}
  \else
    \int_set:Nn \l_tmpb_int {\fpeval{\l_tmpa_int/2}}
    \fp_set:Nn \l_medianea_int {\clist_item:Nn \l_tmpa_clist {\l_tmpb_int}}
    \int_set:Nn \l_tmpb_int {\fpeval{\l_tmpa_int/2+1}}
    \fp_set:Nn \l_medianeb_int {\clist_item:Nn \l_tmpa_clist {\l_tmpb_int}}
    \xdef\Mediane{\fpeval{(\l_medianea_int+\l_medianeb_int)/2}}
  \fi
}%

\NewDocumentCommand\TransformationResultatSondage{m}{%
  \clist_set:Ne \l_tmpa_clist {#1}%
  \clist_clear:N \l_tmpb_clist
  \clist_clear:N \l_tmpc_clist
  \clist_map_inline:Nn \l_tmpa_clist {%
    \clist_if_in:NnTF \l_tmpb_clist {##1} {} {\clist_put_right:Nn \l_tmpb_clist {##1}}
  }%
  \clist_map_inline:Nn \l_tmpb_clist {%
    \int_set:Nn \l_tmpa_int {0}%
    \clist_map_inline:Nn \l_tmpa_clist {%
      \str_if_eq:nnTF {##1} {####1} {\int_incr:N \l_tmpa_int} {}
    }%
    \clist_put_right:Nx \l_tmpc_clist {\int_eval:n {\l_tmpa_int}}
  }%
  \clist_clear:N \l_tmpa_clist
  \int_set:Nn \l_tmpa_int {0}
  \clist_map_variable:NNn \l_tmpb_clist \nba {
    \int_incr:N \l_tmpa_int
    \clist_put_right:Nx \l_tmpa_clist {\nba/\clist_item:Nn \l_tmpc_clist {\int_eval:n {\l_tmpa_int}}}%
  }%
  \edef\PfCSondageListe{\l_tmpa_clist}
}

\NewDocumentCommand\TransformationResultatQuantitatif{m}{%
  \clist_set:Ne \l_tmpa_clist {#1}%
  \clist_clear:N \l_tmpb_clist
  \clist_clear:N \l_tmpc_clist
  \clist_map_inline:Nn \l_tmpa_clist {%
    \clist_if_in:NnTF \l_tmpb_clist {##1} {} {%
      \seq_set_split:Nnn \l_tmpa_seq { / } {##1}
      \clist_put_right:Ne \l_tmpb_clist {\seq_item:Nn \l_tmpa_seq {1}}
      \clist_put_right:Ne \l_tmpc_clist {\seq_item:Nn \l_tmpa_seq {2}}
    }%
  }%
  \clist_sort:Nn \l_tmpb_clist
  {
    \fp_compare:nNnTF { ##1 } > { ##2 }
    { \sort_return_swapped: }
    { \sort_return_same: }
  }
  \clist_clear:N \l_tmpc_clist
  \clist_map_inline:Nn \l_tmpb_clist {%
    \fp_set:Nn \l_tmpb_fp {##1}%
    \clist_map_inline:Nn \l_tmpa_clist {%
      \seq_set_split:Nnn \l_tmpa_seq { / } {####1}
      \fp_set:Nn \l_tmpa_fp {\seq_item:Nn \l_tmpa_seq {1}}
      \fp_compare:nNnTF {\l_tmpa_fp} = {\l_tmpb_fp} {
        \clist_put_right:Ne \l_tmpc_clist {####1}
      } {}
    }%
  }%
  \edef\PfCQuantitatifListe{\l_tmpc_clist}
}
\ExplSyntaxOff

\NewDocumentCommand\PfCCalculQuartileListe{mm}{%
  \ifboolKV[ClesStat]{Liste}{%
    \ifboolKV[ClesStat]{SansRangement}{%
      Les données sont déjà rangées par ordre croissant.\\%
    }{%
      On range les donn\'ees par ordre croissant :%
      \xintifboolexpr{\ListeCompletelen<\useKV[ClesStat]{Coupure}}{%
        \[%
          \xintFor* ##2 in {\xintSeq{1}{\ListeCompletelen}}\do{
            \num{\ListeCompleteRangee[##2]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}\xintifForLast{.}{\,;~}%
            }\]
      }{%
        \begin{center}
          \begin{minipage}{0.9\linewidth}
            \xintFor* ##2 in {\xintSeq{1}{\ListeCompletelen}}\do{%
              \num{\ListeCompleteRangee[##2]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}\xintifForLast{.}{\,;~}\modulo{##2}{\useKV[ClesStat]{Coupure}}\xintifboolexpr{\remainder==0}{\\}{}%
            }%
          \end{minipage}
        \end{center}%
      }%
    }%
    \ifboolKV[ClesStat]{SET}{On sait que }{L'effectif total de la s\'erie est \num{\ListeCompletelen}. Or, }%
    \SI{\fpeval{#1*25}}{\percent} de \num{\ListeCompletelen}, c'est \num{\fpeval{#1*\ListeCompletelen/4}}. Le \ordinalstringnum{#1} quartile $Q_{#1}$ est donc la \num{\fpeval{ceil(#1*\ListeCompletelen/4)}}\PfCieme{} donnée : \[Q_{#1}=\num{#2}.\]%
  }{Pas de quartile possible pour une s\'erie de donn\'ees \`a caract\`ere qualitatif.}%
}%

\NewDocumentCommand\PfCPreparationListe{m}{%
  \setsepchar{,}\ignoreemptyitems%
  \readlist*\Liste{#1}%
  \edef\foo{}%
  \setsepchar[*]{,*/}\ignoreemptyitems%
  \xintFor* ##1 in {\xintSeq {1}{\Listelen}}\do{%
    \edef\foo{\foo 1/\Liste[##1],}%
  }%
  \readlist*\ListeComplete{\foo}%
  \setKV[ClesStat]{Qualitatif}%
}%

\NewDocumentCommand\PfCPreparationSondage{m}{%
  \TransformationResultatSondage{#1}%
  \setsepchar[*]{,*/}\ignoreemptyitems%
  \readlist*\ListeComplete{\PfCSondageListe}%
  \reademptyitems%
  \edef\PfCRetiensQualitatif{0}%
  \foreachitem\x\in\ListeComplete{%
    \IfDecimal{\ListeComplete[\xcnt,1]}{\edef\PfCRetiensQualitatif{\fpeval{\PfCRetiensQualitatif+0}}}{\edef\PfCRetiensQualitatif{\fpeval{\PfCRetiensQualitatif+1}}}%
  }%
  \ifnum\PfCRetiensQualitatif=0\relax%
    \setKV[ClesStat]{Quantitatif}%
    \TransformationResultatQuantitatif{\PfCSondageListe}%
    \setsepchar[*]{,*/}%
    \readlist*\ListeComplete{\PfCQuantitatifListe}%
    \reademptyitems%
  \else%
    \setKV[ClesStat]{Qualitatif}%
  \fi%
}%

\NewDocumentCommand\PfCPreparationQuantitatif{m}{%
  \TransformationResultatQuantitatif{#1}
  \setsepchar[*]{,*/}%
  \readlist*\ListeComplete{\PfCQuantitatifListe}%
  \reademptyitems%
}%

% Pour les classes
% Pour construire l'histogramme
\def\UpdatetoksHisto#1/#2/#3\nil{\addtotok\toklisteelmtsclasse{#1,#2,}\addtotok\toklistedonhisto{#3,}}
\def\UpdatetoksECC#1\nil{\addtotok\toklistedonhisto{#1,}}

\newtoks\toklisteelmtsclasse%
\newtoks\toklistelegende%
\newtoks\toklistedonhisto%
\newtoks\toklistebatonsvides%

\NewDocumentCommand\buildgraphhisto{}{%
  \toklistecouleur{}%
  \toklisteelmtsclasse{}%
  \toklistelegende{}%
  \toklistebatonsvides{}%
  \toklistedonhisto{}%
  \ifboolKV[ClesStat]{LegendeVide}{%
    \xdef\foo{\useKV[ClesStat]{LegendesVides}}%
    \readlist*\ListeLegendesAEffacer{\foo}%
  }{\xdef\foo{-1}\readlist*\ListeLegendesAEffacer{\foo}%
  }%
  \ifemptyKV[ClesStat]{BatonsVides}{%
    \readlist*\ListeBatonsAEffacer{-1}%
  }{%
    \xdef\foo{\useKV[ClesStat]{BatonsVides}}%
    \readlist*\ListeBatonsAEffacer{\foo}%
  }%
  \foreachitem\compteur\in\ListeLegendesAEffacer{\expandafter\UpdateLegende\compteur\nil}%
  \foreachitem\compteur\in\ListeBatonsAEffacer{\expandafter\UpdateBatons\compteur\nil}%
  \foreachitem\compteur\in\ListeDepart{\expandafter\UpdatetoksHisto\compteur\nil}%
  \ifboolKV[ClesStat]{ECC}{%
    \toklistedonhisto{}%
    \xdef\PfCFooECC{\ListeDepart[1,3]}%
    \xintFor* ##1 in{\xintSeq{2}{\ListeDepartlen}}\do{%
      \xdef\PfCFooRetiens{0}%
      \xintFor* ##2 in{\xintSeq{1}{##1}}\do{%
        \xdef\PfCFooRetiens{\fpeval{\PfCFooRetiens+\ListeDepart[##2,3]}}%
      }%
      \xdef\PfCFooECC{\PfCFooECC,\PfCFooRetiens}%
    }%
    \readlist*\PfCListeECC{\PfCFooECC}%
    \foreachitem\compteur\in\PfCListeECC{\expandafter\UpdatetoksECC\compteur\nil}%
  }{}%
  \xdef\PfCEcartClasse{\fpeval{\ListeDepart[1,2]-\ListeDepart[1,1]}}%
  \foreachitem\compteur\in\ListeDepart{%
    \xdef\PfCEcartClasse{\PfCEcartClasse,\fpeval{\ListeDepart[\compteurcnt,2]-\ListeDepart[\compteurcnt,1]}}
  }%
  \xintifboolexpr{\fpeval{min(\PfCEcartClasse)}==\fpeval{max(\PfCEcartClasse)}}{}{\setKV[ClesStat]{MemeAmpli=false}}
  % Pour les couleurs
  \xdef\ListeAvantCouleurs{\useKV[ClesStat]{ListeCouleurs}}%
  \readlist*\ListeCouleur{\ListeAvantCouleurs}%
  \foreachitem\couleur\in\ListeCouleur{\expandafter\UpdateCoul\couleur\nil}%
  %
  \MPBuildHisto{\the\toklisteelmtsclasse}{\the\toklistedonhisto}{\the\toklistecouleur}{\the\toklistelegende}{\the\toklistebatonsvides}%
}

%% calcul des fr\'equences
\newcommand\CalculFrequenceClasses[1]{%
  \fpeval{round(\ListeDepart[#1,3]*100/\EffectifTotal,\useKV[ClesStat]{PrecisionF})}
}

\newcommand\CalculECCClasses[1]{%
  \xdef\TotalECCC{0}%
  \CompteurECCC=1%
  \CompteurECCCTotal=\numexpr#1+1%
  \whiledo{\CompteurECCC < \CompteurECCCTotal}{%
    \xdef\TotalECCC{\fpeval{\TotalECCC+\ListeDepart[\the\CompteurECCC,3]}}%
    \CompteurECCC=\numexpr\CompteurECCC+1%
  }%
  \num{\TotalECCC}%
}

\NewDocumentCommand\buildtabclasses{}{%
  \setcounter{PfCCompteLignes}{0}%
  \renewcommand{\arraystretch}{\useKV[ClesStat]{Stretch}}%
  \begin{NiceTabular}{l*{\ListeDepartlen}{c}}%[hvlines]
    \CodeBefore%
    \rowcolor{\useKV[ClesStat]{CouleurTab}}{1}%
    \columncolor{\useKV[ClesStat]{CouleurTab}}{1}%
    \Body
    \useKV[ClesStat]{Donnee}\xintFor* ##1 in{\xintSeq{1}{\ListeDepartlen}}\do{%
      &\ifboolKV[ClesStat]{Crochets}{$[\num{\ListeDepart[##1,1]}\,;\,\num{\ListeDepart[##1,2]}[$}{$\num{\ListeDepart[##1,1]}\leqslant\dots<\num{\ListeDepart[##1,2]}$}%
    }\\
    \useKV[ClesStat]{Effectif}\xintFor* ##1 in{\xintSeq{1}{\ListeDepartlen}}\do{%
      &\ifboolKV[ClesStat]{EffVide}{}{\num{\ListeDepart[##1,3]}}%
      }\\
      % centre
      \ifboolKV[ClesStat]{Centre}{\stepcounter{PfCCompteLignes}Centre de la classe\xintFor* ##1 in {\xintSeq {1}{\ListeDepartlen}}\do{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{CentreVide}{}{\num{\fpeval{0.5*(\ListeDepart[##1,2]+\ListeDepart[##1,1])}}}}}\\}{}%
      %
    \ifboolKV[ClesStat]{Frequence}{\stepcounter{PfCCompteLignes}Fr\'equence (\%)\xintFor* ##1 in {\xintSeq {1}{\ListeDepartlen}}\do{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{FreqVide}{}{\num{\CalculFrequenceClasses{##1}}}}}\\
    }{}%
    \ifboolKV[ClesStat]{ECC}{\stepcounter{PfCCompteLignes}E.C.C.\xintFor* ##1 in {\xintSeq {1}{\ListeDepartlen}}\do{&\ifboolKV[ClesStat]{TableauVide}{}{\ifboolKV[ClesStat]{ECCVide}{}{\CalculECCClasses{##1}}}}\\}{}%
    \CodeAfter%
    % On crée la liste des colonnes à vider
    \xintifboolexpr{\useKV[ClesStat]{ColVide}>0}{%
      \xdef\FooStat{\useKV[ClesStat]{ColVide}}%
      \setsepchar{,}%
      \readlist*\ListeColonnesAVider{\FooStat}%
      \foreachitem\compteur\in\ListeColonnesAVider{%
        \tikz\fill[white] (row-2-|col-\fpeval{\compteur+1}) rectangle (last-|col-\fpeval{\compteur+2});%
      }%
    }{}%
%    % On crée la liste des cases à vider
    \ifboolKV[ClesStat]{CaseVide}{%
      \xdef\FooStatCases{\useKV[ClesStat]{CasesVides}}%
      \setsepchar[*]{,*/}%
      \readlist*\ListeCasesAVider{\FooStatCases}%
      \foreachitem\compteur\in\ListeCasesAVider{%
        \tikz\fill[white] (row-\fpeval{\ListeCasesAVider[\compteurcnt,1]+1}-|col-\fpeval{\ListeCasesAVider[\compteurcnt,2]+1}) rectangle (row-\fpeval{\ListeCasesAVider[\compteurcnt,1]+2}-|col-\fpeval{\ListeCasesAVider[\compteurcnt,2]+2});%
      }%
    }{}%
%    % On retrace le tableau
%    % Les colonnes
    \xintFor* ##1 in {\xintSeq{1}{\fpeval{\ListeDepartlen+2}}}\do{%
      \tikz\draw (row-1-|col-##1) -- (last-|col-##1);%
    }%
%    % Les lignes
    \xintFor* ##1 in {\xintSeq{1}{\fpeval{\thePfCCompteLignes+3}}}\do{%
      \tikz\draw (row-##1-|col-1) -- (row-##1-|last);%
    }%
  \end{NiceTabular}
}%

\NewDocumentCommand\MPBuildHisto{mmmmm}{%
  \mplibforcehmode%
  \begin{mplibcode}
    defaultcolormodel := \useKV[ClesStat]{ModeleCouleur};
    %
    maxx:=-infinity;
    minx:=infinity;
    maxy:=-infinity;
    miny:=0;
    unitex:=\useKV[ClesStat]{Unitex}*cm;
    unitey:=\useKV[ClesStat]{Unitey}*cm;
    Pasx:=\useKV[ClesStat]{Pasx};
    Pasy:=\useKV[ClesStat]{Pasy};
    UniteAire=\useKV[ClesStat]{UniteAire};
    Ecarthachures=\useKV[ClesStat]{EcartHachures};
    Epaisseurhachures=\useKV[ClesStat]{EpaisseurHachures};
    boolean MemeAmpli,Hachures,Lecture,LectureFine,AideLecture,DonneesSup,Tiret,LegendeVide,Retour,Mediane,ECC,BatonVide;
    ECC=\useKV[ClesStat]{ECC};
    Mediane=\useKV[ClesStat]{Mediane};
    MemeAmpli=\useKV[ClesStat]{MemeAmpli};
    Hachures:=\useKV[ClesStat]{Hachures};
    %
    Lecture:=\useKV[ClesStat]{Lecture};
    LectureFine:=\useKV[ClesStat]{LectureFine};
    Tiret=\useKV[ClesStat]{Tiret};
    AideLecture:=\useKV[ClesStat]{AideLecture};
    DonneesSup:=\useKV[ClesStat]{DonneesSup};
    LegendeVide=\useKV[ClesStat]{LegendeVide};
    \ifemptyKV[ClesStat]{BatonsVides}{BatonVide=false;}{BatonVide=true;}%
    Retour=false;
    % Test affichage
    vardef Test(expr nb)=
      Retour:=false;
      op:=0;
      for l_=#4:
        if l_=nb:
          op:=op+1;
        fi;
      endfor;
      if op>0:
        Retour:=true;
      fi;
    enddef;
    vardef TestBatons(expr nb)=
      Retour:=false;
      op:=0;
      for l_=#5:
        if l_=nb:
          op:=op+1;
        fi;
      endfor;
      if op>0:
        Retour:=true;
      fi;
    enddef;  
    %Affichage ou pas des légendes
    vardef AfficheLegende(text t)=
      l=0;
      for p_=t:
        l:=l+1;
        if DonneesSup:
          Test(l);
          if Retour=false:
            label.top(TEX("\num{"&decimal(Y[l])&"}"),(unitex*(Depart+(0.5*(X[2*l]+X[2*l-2])-X[1])/Pasx),unitey*Z[l]));
          fi;
        fi;
      endfor;
    enddef;
    Depart=\useKV[ClesStat]{DepartHisto};
    % on r\'ecup\`ere les couleurs
    color Col[],CoulDefaut;
    CoulDefaut=white;
    n:=0;
    for p_=#3:
      n:=n+1;
      Col[n]=p_;
    endfor;
    %
    numeric X[];
    numeric ecartabs[];
    vardef RecupValeursAbscisses(text t)=
      p:=0;
      for p_=t:
        p:=p+1;
        X[p]:=p_;
        if X[p]<minx:
          minx:=X[p];
        fi;
        if X[p]>maxx:
          maxx:=X[p];
        fi;
      endfor;
      X[0]=X[1];
      TotalAbscisses=p;
    enddef;
    numeric Y[],Z[];
    numeric EffectifTotal[];
    numeric EffectifTotalA[];
    vardef RecupValeursDonnees(text t)=
      p:=0;
      EffectifTotal[0]:=0;
      EffectifTotalA[0]:=0;
      for p_=t:
        p:=p+1;
        EffectifTotal[p]:=p_;
        EffectifTotalA[p]:=EffectifTotalA[p-1]+p_;
        Y[p]:=p_;
        Z[p]=(Y[p]/(UniteAire*(X[2*p]-X[2*p-1])/Pasx));
        R[p]=ceiling(Z[p]);
        if R[p]>maxy:
          maxy:=R[p];
        fi;
      endfor;
      NbDonnees:=p;
    enddef;
    %On affiche la médiane dans le cas des ECC
    vardef AfficheMedianeECC(text t)=
      YMed:=Z[NbDonnees]/2;
      DemiDonnees:=EffectifTotal[NbDonnees]/2;
      p:=0;
      forever:
        p:=p+1;
        exitif EffectifTotal[p]>DemiDonnees;
      endfor;
      path MedHor,MedLineaire,MedVer;
      MedLineaire=(unitex*(Depart+(X[2*p-2]-X[1]/Pasx)),unitey*Z[p-1])--(unitex*(Depart+(X[2*p]-X[1])/Pasx),unitey*Z[p]);
      MedHor=((0,unitey*YMed)--(unitex*((maxx-minx)/Pasx+2),unitey*YMed));
      MedVer=(xpart(MedLineaire intersectionpoint MedHor),0)--(MedLineaire intersectionpoint MedHor);
      draw MedLineaire;
      draw MedHor;
      draw MedVer;
    enddef;
    % On affiche la médiane dans le cas non ECC
    vardef AfficheMediane(text t)=
      DemiDonnees:=EffectifTotalA[NbDonnees]/2;
      p:=0;
      forever:
        p:=p+1;
        exitif EffectifTotalA[p]>DemiDonnees;
      endfor;
      path MedVer;
      numeric CoefLineaire,pMed;
      pMed=p;
      CoefLineaire=(DemiDonnees-EffectifTotalA[p-1])/Y[p];
      MedVer=(unitex*(Depart+(X[2*p-2]-X[1])/Pasx+CoefLineaire*(X[2*p]-X[2*p-2])/Pasx),0)--(unitex*(Depart+(X[2*p-2]-X[1])/Pasx+CoefLineaire*(X[2*p]-X[2*p-2])/Pasx),unitey*Z[p]);
      draw MedVer dashed evenly;
    enddef;
    % On commence le tracé : on récupère les informations
    RecupValeursAbscisses(#1);
    RecupValeursDonnees(#2);
    % on définit une grille
    vardef Grille=
      if MemeAmpli:
        Ajout:=1;
      else:
        Ajout:=3;
      fi;
      drawoptions(withcolor 0.7white);
      for k=0 upto ((maxx-minx)/Pasx+2+Depart):
        trace (unitex*k,0)--(unitex*k,(maxy+Ajout)*unitey);%withcolor red;
      endfor;
      for k=0 upto (maxy+Ajout):
        trace (0,k*unitey)--(unitex*((maxx-minx)/Pasx+2+Depart),k*unitey);% withcolor blue;
      endfor;
      drawoptions();
    enddef;
    % Fin Grille
    % On trace les rectangles
    vardef AfficheRectangles=
      path Barre[],Chemin[];
      for k=2 step 2 until TotalAbscisses:
        Barre[k]=polygone(unitex*(Depart+(X[k]-X[1])/Pasx,0),(unitex*(Depart+(X[k]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),0));
        Chemin[k]=chemin(unitex*(Depart+(X[k]-X[1])/Pasx,0),(unitex*(Depart+(X[k]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),0));
      endfor;
      if Hachures:
        Grille;
        for k=2 step 2 until TotalAbscisses:
          if BatonVide:
            TestBatons(k div 2);
          fi;
          if Retour=false:
            draw hachurage(Barre[k],60,0.2,0);
            draw Chemin[k];
          fi;
        endfor;
      else:
        for k=2 step 2 until TotalAbscisses:
          if BatonVide:
            TestBatons(k div 2);
          fi;
          if Retour=false:
            fill Barre[k] withcolor if unknown Col[k/2]: CoulDefaut else: Col[k/2] fi;
          fi;
        endfor;
        Grille;
        for k=2 step 2 until TotalAbscisses:
          if BatonVide:
            TestBatons(k div 2);
          fi;
          if Retour=false:
            trace Chemin[k];
          fi;
        endfor;
      fi;
    enddef;
    % Affichage final
    if ECC:
      AfficheRectangles;
      if Mediane:
        AfficheMedianeECC(#2);
      fi;
    else:
      if Mediane:
        AfficheMediane(#2);
        if Hachures:
          Grille;
          % Partie gauche
          for k=2 step 2 until (2*pMed-2):
            draw hachurage(polygone(unitex*(Depart+(X[k]-X[1])/Pasx,0),(unitex*(Depart+(X[k]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),0)),60,0.2,0);
            draw chemin(unitex*(Depart+(X[k]-X[1])/Pasx,0),(unitex*(Depart+(X[k]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),0));
          endfor;
          draw hachurage(polygone(unitex*(Depart+(X[2*pMed-2]-X[1])/Pasx,0),point(0) of MedVer,point(1) of MedVer,(unitex*(Depart+(X[2*pMed-2]-X[1])/Pasx),unitey*Z[pMed])),60,0.2,0);
          draw polygone(unitex*(Depart+(X[2*pMed-2]-X[1])/Pasx,0),point(0) of MedVer,point(1) of MedVer,(unitex*(Depart+(X[2*pMed-2]-X[1])/Pasx),unitey*Z[pMed]));
          % Partie droite
          for k=2*pMed+2 step 2 until TotalAbscisses:
            draw hachurage(polygone(unitex*(Depart+(X[k]-X[1])/Pasx,0),(unitex*(Depart+(X[k]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),0)),120,0.2,1);
            draw chemin(unitex*(Depart+(X[k]-X[1])/Pasx,0),(unitex*(Depart+(X[k]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),0));
          endfor;
          draw hachurage(polygone(unitex*(Depart+(X[2*pMed]-X[1])/Pasx,0),point(0) of MedVer,point(1) of MedVer,(unitex*(Depart+(X[2*pMed]-X[1])/Pasx),unitey*Z[pMed])),120,0.2,1);
          draw polygone(unitex*(Depart+(X[2*pMed]-X[1])/Pasx,0),point(0) of MedVer,point(1) of MedVer,(unitex*(Depart+(X[2*pMed]-X[1])/Pasx),unitey*Z[pMed]));
        else:
          %Partie gauche
          for k=2 step 2 until (2*pMed-2):
            fill polygone(unitex*(Depart+(X[k]-X[1])/Pasx,0),(unitex*(Depart+(X[k]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),0)) withcolor if unknown Col[1]: CoulDefaut else: Col[1] fi;
          endfor;
          fill polygone(unitex*(Depart+(X[2*pMed-2]-X[1])/Pasx,0),point(0) of MedVer,point(1) of MedVer,(unitex*(Depart+(X[2*pMed-2]-X[1])/Pasx),unitey*Z[pMed])) withcolor if unknown Col[1]: CoulDefaut else: Col[1] fi ;
          % Partie droite
          for k=2*pMed+2 step 2 until TotalAbscisses:
            fill polygone(unitex*(Depart+(X[k]-X[1])/Pasx,0),(unitex*(Depart+(X[k]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),0)) withcolor if unknown Col[2]: CoulDefaut else: Col[2] fi;
          endfor;
          fill polygone(unitex*(Depart+(X[2*pMed]-X[1])/Pasx,0),point(0) of MedVer,point(1) of MedVer,(unitex*(Depart+(X[2*pMed]-X[1])/Pasx),unitey*Z[pMed]))  withcolor if unknown Col[2]: CoulDefaut else: Col[2] fi;
          Grille;
          % Partie Gauche
          for k=2 step 2 until (2*pMed-2):
            trace polygone(unitex*(Depart+(X[k]-X[1])/Pasx,0),(unitex*(Depart+(X[k]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),0));
          endfor;
          trace polygone(unitex*(Depart+(X[2*pMed-2]-X[1])/Pasx,0),point(0) of MedVer,point(1) of MedVer,(unitex*(Depart+(X[2*pMed-2]-X[1])/Pasx),unitey*Z[pMed]));%(Y[pMed]/(UniteAire*(X[2*pMed-2]-X[2*pMed-3])/Pasx))));
          for k=2*pMed+2 step 2 until TotalAbscisses:
            draw chemin(unitex*(Depart+(X[k]-X[1])/Pasx,0),(unitex*(Depart+(X[k]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),unitey*(Y[k/2]/(UniteAire*(X[k]-X[k-1])/Pasx))),(unitex*(Depart+(X[k-1]-X[1])/Pasx),0));
          endfor;
          draw polygone(unitex*(Depart+(X[2*pMed]-X[1])/Pasx,0),point(0) of MedVer,point(1) of MedVer,(unitex*(Depart+(X[2*pMed]-X[1])/Pasx),unitey*Z[pMed]));
        fi;
        draw MedVer withpen pencircle scaled 2;
      else:
        AfficheRectangles;
      fi;
    fi;
    %Affichage ou pas des axes, de la médiane
    if MemeAmpli:
      drawarrow (0,0)--unitey*(0,maxy+1);
      EcartAmpli:=(X[2]-X[1])/Pasx;
      if AideLecture:
      for k=2 step 2 until TotalAbscisses:
        trace ((unitex*(Depart+(X[k]-X[1])/Pasx),unitey*Z[k/2]))--(unitey*(0,Z[k/2])) dashed evenly;
        endfor;
      fi;
      if LectureFine:
        for k=0 upto ((maxy+1)):
          if Tiret:
            trace (1pt,k*unitey)--(-1pt,k*unitey);
            label.lft(TEX("\num{"&decimal(k*UniteAire*EcartAmpli)&"}"),(0,k*unitey));
          else:
            dotlabel.lft(TEX("\num{"&decimal(k*UniteAire*EcartAmpli)&"}"),(0,k*unitey));
          fi;
        endfor;
      fi;
      if Lecture:
        for k=0 upto 1:
          if Tiret:
            trace (1pt,k*unitey)--(-1pt,k*unitey);
            label.lft(TEX("\num{"&decimal(k*UniteAire*EcartAmpli)&"}"),(0,k*unitey));
          else:
            dotlabel.lft(TEX("\num{"&decimal(k*UniteAire*EcartAmpli)&"}"),(0,k*unitey));
          fi;
        endfor;
      fi;
    else:%Pas même ampli : on n'affiche pas l'axe vertical
      trace hachurage(polygone((unitex,unitey*(maxy+2)),(unitex*2,unitey*(maxy+2)),(unitex*2,unitey*(maxy+1)),(unitex,unitey*(maxy+1))),60,0.2,0);
      trace polygone((unitex,unitey*(maxy+2)),(unitex*2,unitey*(maxy+2)),(unitex*2,unitey*(maxy+1)),(unitex,unitey*(maxy+1)));
      label.rt(TEX(decimal(UniteAire)&"~\useKV[ClesStat]{Effectif}"),(unitex*2,unitey*(maxy+1.5)));
    fi;
    % On trace l'axe des abscisses
    drawarrow (0,0)--unitex*((maxx-minx)/Pasx+2+Depart,0);
    %On labelise l'axe des abscisses
    dotlabel.bot(TEX("\num{"&decimal(X[1])&"}"),unitex*(Depart,0));
    for k=2 step 2 until TotalAbscisses:
      dotlabel.bot(TEX("\num{"&decimal(X[k])&"}"),unitex*(Depart+(X[k]-X[1])/Pasx,0));
    endfor;
    label.rt(TEX("\useKV[ClesStat]{Donnee}"),(unitex*((maxx-minx)/Pasx+2+Depart),0));
    %On affiche les données sup ou pas.
    AfficheLegende(#2);
  \end{mplibcode}
}%

\newcount\PfMRecapmed%
\newcount\PfMRecapmeda%
\newcount\PfMcountk%
\newcount\PfCQuartileUn%
\newcount\PfCQunk%
\newcount\PfCQuartileTrois%
\newcount\PfCQtroisk%

\NewDocumentCommand\PfCStatQualitatifEffectifTotal{}{%
  \ifboolKV[ClesStat]{Liste}{L'effectif total de la s\'erie est
    \num{\ListeCompletelen}.\par}{%
    \foreachitem\don\in\ListeComplete{\xdef\EffectifTotal{\fpeval{\EffectifTotal+\ListeComplete[\doncnt,2]}}}%
    L'effectif total de la s\'erie est : \[\ListeComplete[1,2]\xintFor* ##1 in
      {\xintSeq {2}{\ListeCompletelen}}\do{%
        +\ListeComplete[##1,2]}=\num{\EffectifTotal}.\]}%
}%

\NewDocumentCommand\PfCStatQualitatifMoyenne{}{%
  \ifPfCDeuxColonnes\relax%
    \setKV[ClesStat]{MVerticale}%
  \fi%
  \ifboolKV[ClesStat]{Liste}{%
    \ifboolKV[ClesStat]{MVerticale}{%
      \ifboolKV[ClesStat]{Somme}{La somme des donn\'ees de la s\'erie est :%
        \xintifboolexpr{\ListeCompletelen<\useKV[ClesStat]{Coupure}}{%
          \begin{align*}
            &\NumMA{\ListeComplete[1,2]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}\\
            \xintFor* ##1 in {\xintSeq {2}{\ListeCompletelen}}\do{%
                +~&\NumMA{\ListeComplete[##1,2]}
                \ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}\\
            }
            \cline{1-2}
            =~&\num{\SommeDonnees}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}.%
          \end{align*}
        }{%
          \begin{align*}
            &\NumMA{\ListeComplete[1,2]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}\\
            \xintFor* ##1 in {\xintSeq {2}{3}}\do{%
              +~&\NumMA{\ListeComplete[##1,2]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}\\}+~&\vdots\\
            \xintFor* ##1 in {\xintSeq {\ListeCompletelen-1}{\ListeCompletelen}}\do{%
                +~&\NumMA{\ListeComplete[##1,2]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}\\
            }\cline{1-2}
            =~&\mathcolor{\useKV[ClesStat]{CouleurSol}}{\num{\SommeDonnees}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}}.%
          \end{align*}
        }%
      }{}%
    }{%
      \ifboolKV[ClesStat]{Somme}{La somme des donn\'ees de la s\'erie est :%
        \xintifboolexpr{\ListeCompletelen<\useKV[ClesStat]{Coupure}}{%
          \[
            \NumMA{\ListeComplete[1,2]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}
              \xintFor* ##1 in {\xintSeq {2}{\ListeCompletelen}}\do{%
                +\NumMA{\ListeComplete[##1,2]}
                \ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}
                }=\num{\SommeDonnees}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}.%
                \]%
       }{%
          \[
            \NumMA{\ListeComplete[1,2]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}
            \xintFor* ##1 in {\xintSeq {2}{3}}\do{%
              +\NumMA{\ListeComplete[##1,2]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}}+\dots\xintFor* ##1 in {\xintSeq {\ListeCompletelen-1}{\ListeCompletelen}}\do{%
                +\NumMA{\ListeComplete[##1,2]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}
           }=\mathcolor{\useKV[ClesStat]{CouleurSol}}{\num{\SommeDonnees}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}}.%
         \]%
        }%
      }{}%
    }%
    \ifboolKV[ClesStat]{MoyenneA}{%
      \ifboolKV[ClesStat]{SET}{}{Le nombre de donn\'ees de la s\'erie est \num{\ListeCompletelen}.\\}%
        Donc la moyenne de la s\'erie est \'egale \`a :%
        \[\frac{\num{\SommeDonnees}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}}{\num{\ListeCompletelen}}%
          \ifboolKV[ClesStat]{ValeurExacte}{}{%
            \opdiv*{\SommeDonnees}{\ListeCompletelen}{resultatmoy}{restemoy}%
            \opround{resultatmoy}{\useKV[ClesStat]{Precision}}{resultatmoy1}%
            \opcmp{resultatmoy}{resultatmoy1}\ifopeq=\else\approx\fi%
            \mathcolor{\useKV[ClesStat]{CouleurSol}}{\num{\fpeval{round(\SommeDonnees/\ListeCompletelen,\useKV[ClesStat]{Precision})}}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}}.%
          }%
        \]%
    }{}%
  }{Pas de moyenne possible pour une s\'erie de donn\'ees \`a caract\`ere qualitatif.}%
}%

\NewDocumentCommand\PfCStatQualitatifEtendue{}{%
  \ifboolKV[ClesStat]{Liste}{%
    L'\'etendue de la s\'erie est \'egale \`a $\num{\DonneeMax}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}-\NumMA{\DonneeMin}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}=\num{\Etendue}$\ifemptyKV[ClesStat]{Unite}{.}{~\useKV[ClesStat]{Unite}.}%
  }{Pas d'\'etendue possible pour une s\'erie de donn\'ees \`a caract\`ere qualitatif.}%
}%

\NewDocumentCommand\PfCStatQualitatifMediane{}{%
  \ifboolKV[ClesStat]{Liste}{%
    \ifboolKV[ClesStat]{SansRangement}{%
      Les données sont déjà rangées par ordre croissant.\\%
    }{%
      On range les donn\'ees par ordre croissant :%
      \xintifboolexpr{\ListeCompletelen<\useKV[ClesStat]{Coupure}}{%
        \[%
          \xintFor* ##2 in {\xintSeq{1}{\ListeCompletelen}}\do{
            \num{\ListeCompleteRangee[##2]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}\xintifForLast{.}{\,;~}%
          }
        \]
      }{%
        \begin{center}
          \begin{minipage}{0.9\linewidth}
            \xintFor* ##2 in {\xintSeq{1}{\ListeCompletelen}}\do{%
              \num{\ListeCompleteRangee[##2]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}\xintifForLast{.}{\,;~}\modulo{##2}{\useKV[ClesStat]{Coupure}}\xintifboolexpr{\remainder==0}{\\}{}%
            }%
          \end{minipage}
        \end{center}%
      }%
    }%
    \ifodd\number\ListeCompletelen%odd impair
      \PfMRecapmed=\fpeval{(\ListeCompletelen+1)/2}\relax%
      \PfMRecapmeda=0%
      \ifboolKV[ClesStat]{SET}{On sait que }{L'effectif total de la s\'erie est \num{\ListeCompletelen}. Or, }$\num{\ListeCompletelen}=\num{\fpeval{\PfMRecapmed-1}}+1+\num{\fpeval{\PfMRecapmed-1}}$.\\
    \else% pair
      \PfMRecapmed=\fpeval{\ListeCompletelen/2}\relax%
      \PfMRecapmeda=\numexpr\PfMRecapmed+1\relax%
      \ifboolKV[ClesStat]{SET}{On sait que }{L'effectif total de la s\'erie est \num{\ListeCompletelen}. Or, }$\num{\ListeCompletelen}=\num{\the\PfMRecapmed}+\num{\the\PfMRecapmed}$.\\
    \fi%
    \ifodd\number\ListeCompletelen%
      La m\'ediane de la s\'erie est la \num{\the\PfMRecapmed}\PfCieme{} donn\'ee.\\Donc la m\'ediane de la s\'erie est \num{\Mediane}\ifemptyKV[ClesStat]{Unite}{.}{~\useKV[ClesStat]{Unite}.}%
    \else%
      La \num{\the\PfMRecapmed}\PfCieme{} donn\'ee est \num{\ListeCompleteRangee[\the\PfMRecapmed]}\ifemptyKV[ClesStat]{Unite}{. }{~\useKV[ClesStat]{Unite}. }%
        % 
      La \num{\the\PfMRecapmeda}\PfCieme{} donn\'ee est \num{\ListeCompleteRangee[\the\PfMRecapmeda]}\ifemptyKV[ClesStat]{Unite}{.}{~\useKV[ClesStat]{Unite}.}\\Donc \PfCArticleMediane{} m\'ediane de la s\'erie est $\ifboolKV[ClesStat]{DetailsMediane}{\dfrac{\num{\Mediane}+\num{\numeroDonnee}}{2}=}{}\num{\Mediane}$\ifemptyKV[ClesStat]{Unite}{.}{~\useKV[ClesStat]{Unite}.}%
    \fi%
    %%%% 
  }{Pas de m\'ediane possible pour une s\'erie de donn\'ees \`a caract\`ere qualitatif.}
}%

\NewDocumentCommand\PfCStatQualitatifTableau{}{%
  \ifboolKV[ClesStat]{Liste}{Pas de tableau possible avec la cl\'e Liste.\\Utilisez plut\^ot la cl\'e Sondage si vous voulez un tableau avec cette liste.}{\ifboolKV[ClesStat]{TabVertical}{\BuildtabStatVertical}{\BuildtabStat}}%
}%

\NewDocumentCommand\PfCStatQualitatifGraphique{o}{%
  \ifboolKV[ClesStat]{Liste}{%
    Pas de graphique possible avec la cl\'e Liste.\\Utilisez plut\^ot la cl\'e Sondage si vous voulez un graphique avec cette liste.%
  }{%
    \ifboolKV[ClesStat]{Barre}{%
      \buildgraphbarhor%
    }{%
      \ifboolKV[ClesStat]{Angle}{%
        \buildgraphcq{360}%
      }{%
        \ifboolKV[ClesStat]{SemiAngle}{%
          \buildgraphcq{180}%
        }{%
          \buildgraphq[#1]%
        }%
      }%
    }%
  }%
}%

\NewDocumentCommand\PfCStatQuantitatifEffectifTotal{}{%
  L'effectif total de la s\'erie est : \[\ListeComplete[1,2]\xintFor* ##1 in
    {\xintSeq {2}{\ListeCompletelen}}\do{%
      +\ListeComplete[##1,2]}=\num{\EffectifTotal}.\]%
}%

\NewDocumentCommand\PfCStatQuantitatifMoyenne{}{%
  \ifPfCDeuxColonnes\relax%
    \setKV[ClesStat]{Coupure=4}%
  \fi%
  \ifboolKV[ClesStat]{Somme}{La somme des donn\'ees de la s\'erie est :%
    \xintifboolexpr{\ListeCompletelen<\useKV[ClesStat]{Coupure}}{%
      \[
       \ifnum\ListeComplete[1,2]=1\else\num{\ListeComplete[1,2]}\times\fi\num{\ListeComplete[1,1]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}\xintFor* ##1 in {\xintSeq {2}{\ListeCompletelen}}\do{%
           +\ifnum\ListeComplete[##1,2]=1\else\num{\ListeComplete[##1,2]}\times\fi\num{\ListeComplete[##1,1]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}
           }=\num{\SommeDonnees}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}.
      \]%
    }{%
      \[
        \ifnum\ListeComplete[1,2]=1\else\num{\ListeComplete[1,2]}\times\fi\num{\ListeComplete[1,1]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}\xintFor* ##1 in {\xintSeq {2}{2}}\do{%
            +\ifnum\ListeComplete[##1,2]=1\else\num{\ListeComplete[##1,2]}\times\fi\num{\ListeComplete[##1,1]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}
            }+\dots\xintFor* ##1 in {\xintSeq {\ListeCompletelen-1}{\ListeCompletelen}}\do{%
              +\ifnum\ListeComplete[##1,2]=1\else\num{\ListeComplete[##1,2]}\times\fi\num{\ListeComplete[##1,1]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}
              }=\num{\SommeDonnees}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}.
      \]%
    }%
  }{}%
  \ifboolKV[ClesStat]{MoyenneA}{%
    \ifboolKV[ClesStat]{SET}{}{L'effectif total de la s\'erie est :%
      \ifboolKV[ClesStat]{Liste}{ \num{\EffectifTotal}\\}{%
          \[\num{\ListeComplete[1,2]}\xintFor* ##1 in {\xintSeq {2}{\ListeCompletelen}}\do{%
              +\num{\ListeComplete[##1,2]}
            }=\num{\EffectifTotal}.
          \]%
      }%
    }%
    Donc la moyenne de la s\'erie est \'egale \`a :%
    \[\frac{\num{\SommeDonnees}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}}{\num{\EffectifTotal}}%
        \ifboolKV[ClesStat]{ValeurExacte}{}{%
          \opdiv*{\SommeDonnees}{\EffectifTotal}{resultatmoy}{restemoy}%
          \opround{resultatmoy}{\useKV[ClesStat]{Precision}}{resultatmoy1}%
          \opcmp{resultatmoy}{resultatmoy1}\ifopeq=\else\approx\fi%
          \mathcolor{\useKV[ClesStat]{CouleurSol}}{\num{\fpeval{round(\SommeDonnees/\EffectifTotal,\useKV[ClesStat]{Precision})}}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}}.%
        }%
    \]%
  }{}%
}%

\NewDocumentCommand\PfCStatQuantitatifEtendue{}{%
  L'\'etendue de la s\'erie est \'egale \`a $\num{\ListeComplete[\ListeCompletelen,1]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}-\NumMA{\ListeComplete[1,1]}\ifemptyKV[ClesStat]{Unite}{}{~\text{\useKV[ClesStat]{Unite}}}=\num{\Etendue}$\ifemptyKV[ClesStat]{Unite}{.}{~\useKV[ClesStat]{Unite}.}%
}%

\NewDocumentCommand\PfCStatQuantitatifMediane{}{%
  \par%
  \ifodd\number\EffectifTotal%odd impair
    \PfMRecapmed=\fpeval{(\EffectifTotal+1)/2}\relax%
    \PfMRecapmeda=0%
    \ifboolKV[ClesStat]{SET}{On sait que }{L'effectif total de la s\'erie est \num{\EffectifTotal}. Or, }$\num{\EffectifTotal}=\num{\fpeval{\PfMRecapmed-1}}+1+\num{\fpeval{\PfMRecapmed-1}}$. %
  \else% pair
    \PfMRecapmed=\fpeval{\EffectifTotal/2}\relax%
    \PfMRecapmeda=\numexpr\PfMRecapmed+1\relax%
    \ifboolKV[ClesStat]{SET}{On sait que }{L'effectif total de la s\'erie est \num{\EffectifTotal}. Or, }$\num{\EffectifTotal}=\num{\fpeval{\PfMRecapmed}}+\num{\fpeval{\PfMRecapmed}}$. %
  \fi%
  \PfMcountk=0%
  \xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{%
    \xintFor* ##2 in {\xintSeq {1}{\ListeComplete[##1,2]}}\do{%
      \PfMcountk=\numexpr\PfMcountk+1\relax%
      \ifnum\PfMcountk=\PfMRecapmed%
        \ifodd\number\EffectifTotal%
          La m\'ediane de la s\'erie est la \num{\the\PfMRecapmed}\PfCieme{} donn\'ee. Donc la m\'ediane de la s\'erie est \num{\ListeComplete[##1,1]}\ifemptyKV[ClesStat]{Unite}{.}{~\useKV[ClesStat]{Unite}.}%
        \else%
          La \num{\the\PfMRecapmed}\PfCieme{} donn\'ee est \num{\ListeComplete[##1,1]}\ifemptyKV[ClesStat]{Unite}{. }{~\useKV[ClesStat]{Unite}. }\xdef\Mediane{\ListeComplete[##1,1]}%
        \fi%
      \fi%
      \ifnum\PfMcountk=\PfMRecapmeda%
        La \num{\the\PfMRecapmeda}\PfCieme{} donn\'ee est \num{\ListeComplete[##1,1]}\ifemptyKV[ClesStat]{Unite}{.}{~\useKV[ClesStat]{Unite}.}\\Donc \PfCArticleMediane{} m\'ediane de la s\'erie est $\ifboolKV[ClesStat]{DetailsMediane}{\dfrac{\num{\Mediane}+\num{\ListeComplete[##1,1]}}2=}{}\xdef\Mediane{\fpeval{(\Mediane+\ListeComplete[##1,1])/2}}\num{\Mediane}$\ifemptyKV[ClesStat]{Unite}{.}{~\useKV[ClesStat]{Unite}.}%
      \fi%
    }%
  }%
}%

\NewDocumentCommand\PfCStatQuantitatifQuartile{mm}{%
  \ifboolKV[ClesStat]{SET}{On sait que }{L'effectif total de la s\'erie est \num{\EffectifTotal}. Or, }\SI{\fpeval{25*#1}}{\percent} de \num{\EffectifTotal}, c'est \num{\fpeval{#1*\EffectifTotal/4}}. Le \ordinalstringnum{#1} quartile $Q_{#1}$ est donc la \num{\fpeval{ceil(#1*\EffectifTotal/4)}}\PfCieme{} donnée : \[Q_{#1}=\num{#2}\ifemptyKV[ClesStat]{Unite}{. }{~\text{\useKV[ClesStat]{Unite}}.}\]
}%

\NewDocumentCommand\PfCStatQuantitatifTableau{}{%
  \ifboolKV[ClesStat]{TabVertical}{\BuildtabStatVertical}{\BuildtabStat}%
}%
  
\NewDocumentCommand\PfCStatQuantitatifGraphique{o}{%
  \ifboolKV[ClesStat]{Moustache}{%
    \buildmoustache%
  }{%
    \ifboolKV[ClesStat]{Angle}{%
      \buildgraphcq{360}%
    }{%
      \ifboolKV[ClesStat]{SemiAngle}{%
        \buildgraphcq{180}%
      }{%
        \buildgraph[#1]%
      }%
    }%
  }%
}%

\NewDocumentCommand\Stat{om}{%
  %Debut Stat
  \useKVdefault[ClesStat]%
  \setKV[ClesStat]{#1}%
  \ifPfCDeuxColonnes\relax%
    \setKV[ClesStat]{TabVertical}%
  \fi%
  \ifboolKV[ClesStat]{UneMediane}{\renewcommand{\PfCArticleMediane}{une}}{\renewcommand{\PfCArticleMediane}{la}}%
  \ifboolKV[ClesStat]{Nuage}{%
    \StatNuage[#1]{#2}%
  }{%
  \ifboolKV[ClesStat]{Multi}{%
    \StatMulti[#1]{#2}%
  }{%
    \setsepchar[*]{,*/}%
    \readlist*\ListeAvantUtilisation{#2}%
    \xintifboolexpr{\listlen\ListeAvantUtilisation[1]==3}{\setKV[ClesStat]{Classes}}{}%
    \ifboolKV[ClesStat]{Classes}{%
      \PfMBuildClasses{#2}%
    }{%
      \setsepchar{,}%
      \ifboolKV[ClesStat]{Representation}{%
        \setKV[TraceG]{Xmin=0,Ymin=0}%
        \setKV[TraceG]{#1}%
        \readlist*\ListePointsPlaces{#2}%
        \newtoks\toklistepoint%
        \foreachitem\compteur\in\ListePointsPlaces{\expandafter\Updatetoks\compteur\nil}%
        \MPPlacePoint[#1]{\the\toklistepoint}%
      }{%
        \ifboolKV[ClesStat]{Liste}{%
          \PfCPreparationListe{#2}%
        }{%
          \ifboolKV[ClesStat]{Sondage}{%
            \PfCPreparationSondage{#2}%
          }{%
            \ifboolKV[ClesStat]{Qualitatif}{%
              \edef\PfCRetiensListeDonnees{#2}
              \setsepchar[*]{,*/}\ignoreemptyitems%%
              \readlist*\ListeComplete{\PfCRetiensListeDonnees}%
              \reademptyitems%
            }{%
              \PfCPreparationQuantitatif{#2}%
            }%
          }%
        }%
        \edef\PfCListeARanger{}%
        \foreachitem\x\in\ListeComplete{%
          \itemtomacro\ListeComplete[\xcnt,2]\y%
          \edef\PfCListeARanger{\PfCListeARanger,\y}%
        }%
        \Rangement*[Seul]{\PfCListeARanger}%
        \setsepchar{,}\ignoreemptyitems%
        \readlist*\ListeCompleteRangee{\PfCRetiensRangement}%
        \reademptyitems%
        %  % on r\'einitialise les valeurs des crit\`eres de position et de
        % dispersion
        \renewcommand\NbDonnees{}%
        \renewcommand\SommeDonnees{}%
        \renewcommand\EffectifTotal{}%
        \renewcommand\Moyenne{}%
        \renewcommand\Etendue{}%
        \renewcommand\Mediane{}%
        \renewcommand\DonneeMax{-999999999}%
        \renewcommand\EffectifMax{0}%
        \renewcommand\DonneeMin{999999999}%
%        %Choix Quan/QualA%
        \ifboolKV[ClesStat]{Qualitatif}{%D\'ebut qualitatif
%          % Calculs
%          %  %% celui de la somme des donn\'ees
          \foreachitem\don\in\ListeComplete{\xdef\SommeDonnees{\fpeval{\SommeDonnees+\ListeComplete[\doncnt,2]}}}%
          \ifboolKV[ClesStat]{Liste}{\xdef\EffectifTotal{\ListeCompletelen}}{\xdef\EffectifTotal{\SommeDonnees}}%
          \xdef\Moyenne{\fpeval{\SommeDonnees/\ListeCompletelen}}%
          \xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{%
            \xintifboolexpr{\ListeComplete[##1,2]>\DonneeMax}{%
              \xdef\DonneeMax{\ListeComplete[##1,2]}%
            }{}%
            \xintifboolexpr{\ListeComplete[##1,2]<\DonneeMin}{%
              \xdef\DonneeMin{\ListeComplete[##1,2]}%
            }{}%
          }%
          \xdef\EffectifMax{\DonneeMax}%
          \xdef\Etendue{\fpeval{\DonneeMax-\DonneeMin}}%
          % Recuperation de la mediane
          \CalculMedianeListe{\PfCRetiensRangement}%
          %
          \PfCQuartileUn=\fpeval{ceil(\ListeCompletelen/4)}%
          \xdef\QuartileUn{\ListeCompleteRangee[\PfCQuartileUn]}%
          % 
          \PfCQuartileTrois=\fpeval{ceil(3*\ListeCompletelen/4)}%
          \xdef\QuartileTrois{\ListeCompleteRangee[\PfCQuartileTrois]}%
          \ifemptyKV[ClesStat]{Ordre}{%
            % celui de l'effectif total
            \ifboolKV[ClesStat]{EffectifTotal}{%
              \PfCStatQualitatifEffectifTotal%
            }{}%
            % celui de la moyenne
            \ifboolKV[ClesStat]{Moyenne}{%
              \PfCStatQualitatifMoyenne%
            }{}
            % celui de l'\'etendue
            \ifboolKV[ClesStat]{Etendue}{%
              \PfCStatQualitatifEtendue%
            }{}%
            % celui de la mediane
            \ifboolKV[ClesStat]{Mediane}{%
              \PfCStatQualitatifMediane%
            }{}%
            % Quartile un
            \ifboolKV[ClesStat]{QuartileUn}{%
              \PfCCalculQuartileListe{1}{\QuartileUn}%
            }{}%
            % Quartile trois
            \ifboolKV[ClesStat]{QuartileTrois}{%
              \PfCCalculQuartileListe{3}{\QuartileTrois}%
            }{}%
            % Construction du tableau
            \ifboolKV[ClesStat]{Tableau}{%
             \PfCStatQualitatifTableau%
            }{}%
            % Construction du graphique
            \ifboolKV[ClesStat]{Graphique}{%
                \PfCStatQualitatifGraphique[#1]%
            }{}%
           % Fin Qual
          }{%
            %Ordre n'est pas vide
            \edef\PfMLectureOrdre{\useKV[ClesStat]{Ordre}}%
            \setsepchar{,}\ignoreemptyitems%
            \readlist*\ListeOrdreCalcul{\PfMLectureOrdre}%
            \reademptyitems%
            \foreachitem\TypeOrdre\in\ListeOrdreCalcul{%
              \par
             \IfStrEqCase{\TypeOrdre}{%
                {EffectifTotal}{\setKV[ClesStat]{EffectifTotal}\PfCStatQualitatifEffectifTotal}%
                {Moyenne}{\setKV[ClesStat]{Moyenne}\PfCStatQualitatifMoyenne}%
                {Etendue}{\setKV[ClesStat]{Etendue}\PfCStatQualitatifEtendue}%
                {Mediane}{\setKV[ClesStat]{Mediane}\PfCStatQualitatifMediane}%
                {QuartileUn}{\setKV[ClesStat]{QuartileUn}\PfCCalculQuartileListe{1}{\QuartileUn}}%
                {QuartileTrois}{\setKV[ClesStat]{QuartileTrois}\PfCCalculQuartileListe{3}{\QuartileTrois}}%
                {Tableau}{\setKV[ClesStat]{Tableau}\PfCStatQualitatifTableau}%
                {Graphique}{\setKV[ClesStat]{Graphique}\PfCStatQualitatifGraphique[#1]}%
              }%
            }%
          }%
          }{%D\'ebut quantitatif
%          % on effectue les calculs
%          % celui de la somme des donn\'ees
        \foreachitem\don\in\ListeComplete{\xdef\SommeDonnees{\fpeval{\SommeDonnees+\ListeComplete[\doncnt,1]*\ListeComplete[\doncnt,2]}}}%
%        %  %% celui de l'effectif total
        \foreachitem\don\in\ListeComplete{\xdef\EffectifTotal{\fpeval{\EffectifTotal+\ListeComplete[\doncnt,2]}}}%
%        %  %% celui de l'\'etendue
        \xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{%
          \xintifboolexpr{\ListeComplete[##1,1]>\DonneeMax}{%
            \xdef\DonneeMax{\ListeComplete[##1,1]}%
          }{}%
          \xintifboolexpr{\ListeComplete[##1,1]<\DonneeMin}{%
            \xdef\DonneeMin{\ListeComplete[##1,1]}%
          }{}%
        }%
        \xdef\Etendue{\fpeval{\DonneeMax-\DonneeMin}}%%
%        %  %% celui de la moyenne
        \xdef\Moyenne{\fpeval{\SommeDonnees/\EffectifTotal}}%
        % mediane
        \ifodd\number\EffectifTotal%odd impair
          \PfMRecapmed=\fpeval{(\EffectifTotal+1)/2}\relax%
        \else% pair
          \PfMRecapmed=\fpeval{\EffectifTotal/2}\relax%
          \PfMRecapmeda=\numexpr\PfMRecapmed+1\relax%
        \fi%
        \PfMcountk=0%
        \xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{%
          \xintFor* ##2 in {\xintSeq {1}{\ListeComplete[##1,2]}}\do{%
            \PfMcountk=\numexpr\PfMcountk+1\relax%
            \ifnum\PfMcountk=\PfMRecapmed%
              \ifodd\number\EffectifTotal%
                \xdef\Mediane{\ListeComplete[##1,1]}%
              \else%
                \xdef\Mediane{\ListeComplete[##1,1]}%
              \fi%
            \fi%
            \ifnum\PfMcountk=\PfMRecapmeda%
              \xdef\Mediane{\fpeval{(\Mediane+\ListeComplete[##1,1])/2}}%
            \fi%
          }%
        }%
        \PfCQuartileUn=\fpeval{ceil(\EffectifTotal/4)}%
        \PfCQunk=0%
        \xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{%
          \PfCQunk=\numexpr\PfCQunk+\ListeComplete[##1,2]\relax%
          \xintifboolexpr{\PfCQunk<\PfCQuartileUn}{}{\xdef\QuartileUn{\ListeComplete[##1,1]}\xintBreakFor*}%
%          \ifnum\PfCQunk<\PfCQuartileUn\relax\else%
%            \xdef\QuartileUn{\ListeComplete[##1,1]}%
%            \xintBreakFor*
%          \fi%
        }%
        \PfCQuartileTrois=\fpeval{ceil(3*\EffectifTotal/4)}%
        \PfCQtroisk=0%
        \xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{%
          \PfCQtroisk=\numexpr\PfCQtroisk+\ListeComplete[##1,2]\relax%
          \xintifboolexpr{\PfCQtroisk<\PfCQuartileTrois}{}{\xdef\QuartileTrois{\ListeComplete[##1,1]}\xintBreakFor*}%
%          \ifnum\PfCQtroisk<\PfCQuartileTrois\relax\else%
%            \xdef\QuartileTrois{\ListeComplete[##1,1]}%
%            \xintBreakFor*
%          \fi%
        }%  
        %
        \ifemptyKV[ClesStat]{Ordre}{%
          % Affichage des r\'eponses.        
          \ifboolKV[ClesStat]{EffectifTotal}{%
            \PfCStatQuantitatifEffectifTotal%
          }{}%
          \ifboolKV[ClesStat]{Moyenne}{%
            \PfCStatQuantitatifMoyenne%
          }{}%
          % pour l'\'etendue
          \ifboolKV[ClesStat]{Etendue}{%
            \PfCStatQuantitatifEtendue%
          }{}%
          % pour la m\'ediane
          \ifboolKV[ClesStat]{Mediane}{%
            \PfCStatQuantitatifMediane%
          }{}%
          % Quartile un
          \ifboolKV[ClesStat]{QuartileUn}{%
           \PfCStatQuantitatifQuartile{1}{\QuartileUn}%
          }{}%
          % Quartile trois
          \ifboolKV[ClesStat]{QuartileTrois}{%
            \PfCStatQuantitatifQuartile{3}{\QuartileTrois}%
          }{}%
         % Construction de tableau
          \ifboolKV[ClesStat]{Tableau}{%
            \PfCStatQuantitatifTableau%
          }{}%
          % Construction du graphique ??
          \ifboolKV[ClesStat]{Graphique}{%
           \PfCStatQuantitatifGraphique[#1]%
          }{}%
          % Fin Quant%
        }{%
          \edef\PfMLectureOrdre{\useKV[ClesStat]{Ordre}}%
          \setsepchar{,}\ignoreemptyitems%
         \readlist*\ListeOrdreCalcul{\PfMLectureOrdre}%
          \reademptyitems%
          \foreachitem\TypeOrdre\in\ListeOrdreCalcul{%
            \par
            \IfStrEqCase{\TypeOrdre}{%
              {EffectifTotal}{\setKV[ClesStat]{EffectifTotal}\PfCStatQuantitatifEffectifTotal}%
             {Moyenne}{\setKV[ClesStat]{Moyenne}\PfCStatQuantitatifMoyenne}%
              {Etendue}{\setKV[ClesStat]{Etendue}\PfCStatQuantitatifEtendue}%
              {Mediane}{\setKV[ClesStat]{Mediane}\PfCStatQuantitatifMediane}%
              {QuartileUn}{\setKV[ClesStat]{QuartileUn}\PfCStatQuantitatifQuartile{1}{\QuartileUn}}%
              {QuartileTrois}{\setKV[ClesStat]{QuartileTrois}\PfCStatQuantitatifQuartile{3}{\QuartileTrois}}%
              {Tableau}{\setKV[ClesStat]{Tableau}\PfCStatQuantitatifTableau}%
              {Graphique}{\setKV[ClesStat]{Graphique}\PfCStatQuantitatifGraphique[#1]}%
            }%
          }%
        }%
      }%
    }%
  }%
}%
}%
%Fin Stat
}%

\NewDocumentCommand\PfMBuildClasses{m}{%
  \setsepchar[*]{,*/}%
  \readlist*\ListeDepart{#1}%
  \xdef\EffectifTotal{0}%
  \xintFor* ##1 in{\xintSeq{1}{\ListeDepartlen}}\do{%
    \xdef\EffectifTotal{\fpeval{\EffectifTotal+\ListeDepart[##1,3]}}%
  }%
  \ifboolKV[ClesStat]{Histogramme}{%
    \buildgraphhisto%
  }{%
    \ifboolKV[ClesStat]{Tableau}{%
      \buildtabclasses%
    }{}%
  }%
}%

%%%%%%%%%%%%% Pour les multi
\setKVdefault[StatMulti]{ListeCouleurs={white,black},Grille=false,Pasx=1,Pasy=1,PasGrillex=1,PasGrilley=1,Unitex=1,Unitey=0.5,GrandNombrey=false,Depart=0,Tiret=false,Largeur=1,Ecart=0.5,LegendeX={},LegendeY={},Titre={},Legendes={A,B},DonneesSup=false,LegendesH=false,SansAxeOrd=false,Epaisseur=1,Hachures=false,DessinVide=false,Vide=false,Vertical=false,Superpose=false}
\defKV[StatMulti]{GrandNombreO=\setKV[StatMulti]{GrandNombrey}}%
\defKV[StatMulti]{NonTraces=\setKV[StatMulti]{DessinVide}}%
\newtoks\TokzSMultiAbs%
\newtoks\TokzSMultiOrd%
\newtoks\TokzSMultiLegende%
\def\UpdateToksSMultiAbs#1\nil{\addtotok\TokzSMultiAbs{"#1",}}%
\def\UpdateToksSMultiOrd#1\nil{\addtotok\TokzSMultiOrd{#1,}}%
\def\UpdateToksSMultiLegende#1\nil{\addtotok\TokzSMultiLegende{"#1",}}%

\NewDocumentCommand\StatMulti{om}{%
  \TokzSMultiAbs{}%
  \TokzSMultiOrd{}%
  \TokzSMultiLegende{}%
  \useKVdefault[StatMulti]%
  \setKV[StatMulti]{#1}%
  \edef\PfCFoo{#2}%
  \setsepchar[*]{,*/}\ignoreemptyitems%
  \readlist*\ListeDonneesG{\PfCFoo}%
  \reademptyitems%
  \edef\PfMNombreAParcourir{\fpeval{\listlen\ListeDonneesG[1]}}%
  \xintFor* ##1 in{\xintSeq{1}{\ListeDonneesGlen}}\do{%
    \expandafter\UpdateToksSMultiAbs\ListeDonneesG[##1,1]\nil%
  }%
  \xintFor* ##2 in{\xintSeq{2}{\PfMNombreAParcourir}}\do{%
    \xintFor* ##1 in{\xintSeq{1}{\ListeDonneesGlen}}\do{%
      \expandafter\UpdateToksSMultiOrd\ListeDonneesG[##1,##2]\nil%
    }%
  }%
  \edef\ListeAvantCouleurs{\useKV[StatMulti]{ListeCouleurs}}%
  \edef\ListeOrd{\the\TokzSMultiOrd}%
  \edef\ListeAbs{\the\TokzSMultiAbs}%
  \edef\ListeLegendesAv{\useKV[StatMulti]{Legendes}}%
  \setsepchar{,}\ignoreemptyitems%
  \readlist*\ListeLegendes{\ListeLegendesAv}%
  \reademptyitems%
  \foreachitem\PfMCompteurL\in\ListeLegendes{%
    \expandafter\UpdateToksSMultiLegende\PfMCompteurL\nil%
  }%
  \ifboolKV[StatMulti]{DessinVide}{%
    \edef\PfMTracesAEffacer{\useKV[StatMulti]{NonTraces}}%
  }{%
    \edef\PfMTracesAEffacer{}%
  }%
  \ifboolKV[StatMulti]{Superpose}{%
    \BuildMPStatMultiBatons{\ListeAbs}{\ListeOrd}{\PfMNombreAParcourir}{\ListeAvantCouleurs}{\the\TokzSMultiLegende}{\PfMTracesAEffacer}%
  }{%
    \ifboolKV[StatMulti]{Vertical}{%
      \BuildMPStatMultiVertical{\ListeAbs}{\ListeOrd}{\PfMNombreAParcourir}{\ListeAvantCouleurs}{\the\TokzSMultiLegende}{\PfMTracesAEffacer}%
    }{%
      \BuildMPStatMulti{\ListeAbs}{\ListeOrd}{\PfMNombreAParcourir}{\ListeAvantCouleurs}{\the\TokzSMultiLegende}{\PfMTracesAEffacer}%
    }%
  }%
}%

\def\MPStatMultiNewCode{%
  maxx=0;
  maxy=0;
  unitex=\useKV[StatMulti]{Unitex}*cm;
  unitey=\useKV[StatMulti]{Unitey}*cm;
  LargB=\useKV[StatMulti]{Largeur};
  EcartB=\useKV[StatMulti]{Ecart};
  Epaisseur=\useKV[StatMulti]{Epaisseur};
  boolean Tiret,GrandNombrey,Grille,DonneesSup,LegendesH,SansAxeOrd,Hachures,DessinVide,Visible,Vide;
  Visible=true;
  GrandNombrey=\useKV[StatMulti]{GrandNombrey};
  if GrandNombrey:
    GrandNombreO=\useKV[StatMulti]{GrandNombreO};
  fi;
  DessinVide=\useKV[StatMulti]{DessinVide};
  Vide=\useKV[StatMulti]{Vide};
  Hachures=\useKV[StatMulti]{Hachures};
  DonneesSup:=\useKV[StatMulti]{DonneesSup};
  LegendesH=\useKV[StatMulti]{LegendesH};
  SansAxeOrd=\useKV[StatMulti]{SansAxeOrd};
  Tiret=\useKV[StatMulti]{Tiret};
  Grille:=\useKV[StatMulti]{Grille};
  Pasx:=\useKV[StatMulti]{Pasx};
  Pasy:=\useKV[StatMulti]{Pasy};
  PasGrillex:=\useKV[StatMulti]{PasGrillex};
  PasGrilley:=\useKV[StatMulti]{PasGrilley};
  color CoulDefaut;
  CoulDefaut=white;
  Depart=\useKV[StatMulti]{Depart};
  %
  pair A[][],B[][];
  numeric Ord[];
  vardef RecuperationOrdo(text t)=%points qualitatif
    n:=0;
    for p_=t:
      n:=n+1;
      Ord[n]=p_-Depart;
    endfor;
  enddef;
}%

\NewDocumentCommand\BuildMPStatMulti{mmmmmm}{%
  % #1 les labels des abscisses
  % #2 la liste des ordonnées
  % #3 le nombre de valeurs par abscisse
  % #4 les couleurs
  % #5 les légendes
  % #6 les numéros des rectangles à ne pas tracer : Attention à ne pas oublier que les rectangles sont construits par couleur et non de gauche à droite.
    \mplibforcehmode%
    \begin{mplibcode}
      defaultcolormodel := \useKV[ClesStat]{ModeleCouleur};
      %
      \MPStatMultiNewCode
      %
      vardef TestVisibilite(expr nb)=
        Visible:=true;
        op:=0;
        for l_=#6:
          if l_=nb:
            op:=op+1;
          fi;
        endfor;
        if op>0:
          Visible:=false;
        fi;
      enddef;
      % On détermine le décalage max en abscisse.
      nbdonnees=0;
      for l_=#1:
        nbdonnees:=nbdonnees+1;
      endfor;
      maxx:=nbdonnees*((#3-1)*LargB+EcartB);
      maxy:=max(#2);
      %
      % On récupère les ordonnées
      RecuperationOrdo(#2);
      % on récupère les couleurs
      color Coul[];
      for k=1 upto #3:
        Coul[k]=CoulDefaut;
      endfor;
      n:=0;
      for p_=#4:
        n:=n+1;
        if color p_:
          Coul[n]:=p_;
        fi;
      endfor;
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      if Grille:
        drawoptions(withcolor 0.75white);
        for k=0 step PasGrilley until ceiling(maxy/Pasy)*Pasy:
          trace (0,k*unitey)--(unitex*(maxx+1),k*unitey);
        endfor;
        drawoptions();
      fi;
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Tracé et remplissage %%%%%%%%%%%%%%%
      %%%%%%%% définition des points et tracés des polygones.
      for k=1 upto nbdonnees:
        for l=1 upto #3-1:
          NumOrd:=k+nbdonnees*(l-1);
          A[l][k]=((0.5+(l-1)*LargB)*unitex,0) shifted ((k-1)*unitex*((#3-1)*LargB+EcartB,0));
          B[l][k]=A[l][k]+unitey*(0,Ord[NumOrd]);
          if Vide=false:
            if DessinVide:
              TestVisibilite(NumOrd);
            fi;
            if Visible:
              if Hachures:
                trace Hachurage(polygone(A[l][k],B[l][k],B[l][k]+unitex*(LargB,0),A[l][k]+unitex*(LargB,0)),15+(l-1)*(180/#3),0.15,0) withpen pencircle scaled Epaisseur;
                trace polygone(A[l][k],B[l][k],B[l][k]+unitex*(LargB,0),A[l][k]+unitex*(LargB,0))withpen pencircle scaled Epaisseur;
              else:
                fill polygone(A[l][k],B[l][k],B[l][k]+unitex*(LargB,0),A[l][k]+unitex*(LargB,0)) withcolor Coul[l];
                trace polygone(A[l][k],B[l][k],B[l][k]+unitex*(LargB,0),A[l][k]+unitex*(LargB,0));
              fi;
            fi;
          fi;
        endfor;
      endfor;
      %%%%%%%% Affichage des données ou pas
      if DonneesSup:
        for k=1 upto nbdonnees:
          for l=1 upto #3-1:
            NumOrd:=k+nbdonnees*(l-1);
            if Vide=false:
              if DessinVide:
                TestVisibilite(NumOrd);
              fi;
              if Visible:
                label.top(TEX("\num{"&decimal(Ord[NumOrd])&"}"),B[l][k]+unitex*(0.5*LargB,0));
              fi;
            fi;
          endfor;
        endfor;
      fi;
      %%%%%%%% "Graduations" x
      for k=0 upto nbdonnees-1:
        drawoptions(shifted (k*unitex*((#3-1)*LargB+EcartB,0)));
        trace (0.5*unitex,-1pt)--(0.5*unitex,1pt);
        for l=1 upto #3-1:
          trace ((0.5+l*LargB)*unitex,-1pt)--((0.5+l*LargB)*unitex,1pt);
        endfor;
        drawoptions();
      endfor;
      %%%%%%%% Graduations y
      for k=0 step Pasy until ceiling(maxy/Pasy)*Pasy:
        if GrandNombrey:
          label.lft(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreO}*"&decimal(k+Depart)&"}}"),(0,k*unitey));
        else:
          label.lft(TEX("\num{"&decimal(k+Depart)&"}"),(0,k*unitey));
        fi;
        if Tiret:
          trace (1pt,k*unitey)--(-1pt,k*unitey);
        else:
          fill cercles((0,k*unitey),1pt);
        fi;
      endfor;
      %%%%%%%% Axes et labelisation
      if Hachures:
        drawoptions(withpen pencircle scaled Epaisseur);
      fi;
      drawarrow (0,0)--unitex*(maxx+1,0);
      if SansAxeOrd=false:
        drawarrow (0,0)--unitey*(0,ceiling(maxy/Pasy)*Pasy);
      fi;
      drawoptions();
      nb:=0;
      for p_=#1:
        nb:=nb+1;
        label.bot(TEX(p_),1/2[A[1][nb],A[#3-1][nb]+unitex*(LargB,0)]);
      endfor;
      picture RetiensPicture;
      RetiensPicture=currentpicture;
      label.bot(TEX("\useKV[StatMulti]{LegendeX}"),iso(llcorner RetiensPicture,lrcorner RetiensPicture));
      label.lft(TEX("\useKV[StatMulti]{LegendeY}") rotated 90,iso(llcorner RetiensPicture,ulcorner RetiensPicture));
      label.top(TEX("\useKV[StatMulti]{Titre}"),iso(ulcorner RetiensPicture,urcorner RetiensPicture));
      %%%%%%%% Legende des couleurs
      n:=0;
      if LegendesH:
        for p_=#5:
          n:=n+1;
          if Hachures:
            trace Hachurage((unitsquare xscaled 3mm yscaled 6mm) shifted(((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0,-1)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0)),15+(n-1)*(180/#3),0.15,0) withpen pencircle scaled Epaisseur;
            trace (unitsquare xscaled 3mm yscaled 6mm) shifted(((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0,-1)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0)) withpen pencircle scaled Epaisseur;
          else:
            fill (unitsquare scaled 3mm) shifted(((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0,-1)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0)) withcolor Coul[n];
            trace (unitsquare scaled 3mm) shifted(((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0,-1)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0));
          fi;
          label.rt(TEX(p_),((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0.3,-0.85)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0));
        endfor;
      else:
        for p_=#5:
          n:=n+1;
          if Hachures:
            trace Hachurage((unitsquare xscaled 6mm yscaled 3mm) shifted(urcorner RetiensPicture+5mm*(1,-n)) ,15+(n-1)*(180/#3),0.15,0) withpen pencircle scaled Epaisseur;
            trace (unitsquare xscaled 6mm yscaled 3mm) shifted(urcorner RetiensPicture+5mm*(1,-n)) withpen pencircle scaled Epaisseur;
            label.rt(TEX(p_),urcorner RetiensPicture+5mm*(2.4,-0.75-(n-1)));
          else:
            fill (unitsquare scaled 3mm) shifted(urcorner RetiensPicture+5mm*(1,-n)) withcolor Coul[n];
            trace (unitsquare scaled 3mm) shifted(urcorner RetiensPicture+5mm*(1,-n));
            label.rt(TEX(p_),urcorner RetiensPicture+5mm*(1.5,-0.75-(n-1)));
          fi;
        endfor;
      fi;
    \end{mplibcode}%
}%

\NewDocumentCommand\BuildMPStatMultiVertical{mmmmmm}{%
  % #1 les labels des abscisses
  % #2 la liste des ordonnées
  % #3 le nombre de valeurs par abscisse
  % #4 les couleurs
  % #5 les légendes
  % #6 les numéros des rectangles à ne pas tracer : Attention à ne pas oublier que les rectangles sont construits par couleur et non de gauche à droite.
    \mplibforcehmode%
    \begin{mplibcode}
      defaultcolormodel := \useKV[ClesStat]{ModeleCouleur};
      % 
      \MPStatMultiNewCode
      %
      numeric OrdV[][];
      vardef RecuperationOrdoV(text t)=%points qualitatif
        n:=0;
        for p_=t:
          n:=n+1;
          OrdV[n]=p_;
        endfor;
      enddef;
      %
      vardef TestVisibilite(expr nb)=
        Visible:=true;
        op:=0;
        for l_=#6:
          if l_=nb:
            op:=op+1;
          fi;
        endfor;
        if op>0:
          Visible:=false;
        fi;
      enddef;
      % On détermine le décalage max en abscisse.
      nbdonnees=0;
      for l_=#1:
        nbdonnees:=nbdonnees+1;
      endfor;
      maxx:=nbdonnees*LargB+(nbdonnees-1)*EcartB;
      %
      % On récupère les ordonnées
      RecuperationOrdoV(#2);
      nbordpardon=n div nbdonnees;
      maxy:=0;
      for k=1 upto nbdonnees:
        sumy:=0;
        for l=1 upto nbordpardon:
          sumy:=sumy+OrdV[(l-1)*nbdonnees+k];
        endfor;
        if sumy>maxy:
          maxy:=sumy;
        fi;
      endfor;
      maxy:=maxy-Depart;
      % on récupère les couleurs
      color Coul[];
      for k=1 upto #3:
        Coul[k]=CoulDefaut;
      endfor;
      n:=0;
      for p_=#4:
        n:=n+1;
        if color p_:
          Coul[n]:=p_;
        fi;
      endfor;
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      if Grille:
        drawoptions(withcolor 0.75white);
        for k=0 step PasGrilley until ceiling(maxy/Pasy)*Pasy:
          trace (0,k*unitey)--(unitex*(maxx+1),k*unitey);
        endfor;
        drawoptions();
      fi;
      %%%%%%%%%%%%%%%%%%%%%
      %
      %%%%%%%%%%%%%%%%%%%%%
      %%%%%%%% "Graduations" x
      for k=0 upto nbdonnees-1:
        drawoptions(shifted (k*unitex*(LargB+EcartB,0)));
        trace (0.5*unitex,-1pt)--(0.5*unitex,1pt);
        trace ((0.5+LargB)*unitex,-1pt)--((0.5+LargB)*unitex,1pt);
        drawoptions();
      endfor;
      %%%%%%%% Graduations y
      for k=0 step Pasy until ceiling(maxy/Pasy)*Pasy:
        if GrandNombrey:
          label.lft(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreO}*"&decimal(k+Depart)&"}}"),(0,k*unitey));
        else:
          label.lft(TEX("\num{"&decimal(k+Depart)&"}"),(0,k*unitey));
        fi;
        if Tiret:
          trace (1pt,k*unitey)--(-1pt,k*unitey);
        else:
          fill cercles((0,k*unitey),1pt);
        fi;
      endfor;
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Tracé et remplissage %%%%%%%%%%%%%%%
      %%%%%%%% définition des points et tracés des polygones.
      for l=1 upto nbdonnees:
        Sum[l]=0;
      endfor;
      for k=1 upto nbdonnees:
        for l=1 upto #3-1:
          NumOrd:=k+nbdonnees*(l-1);
          A[l][k]=((0.5+(k-1)*LargB)*unitex,0) shifted ((unitex*(k-1)*EcartB,unitey*Sum[k]));
          B[l][k]=A[l][k]+unitey*(0,OrdV[NumOrd] if k=1:-Depart fi);
          Sum[k]:=Sum[k]+OrdV[NumOrd] if l=1:-Depart fi;
          if Vide=false:
            if DessinVide:
              TestVisibilite(NumOrd);
            fi;
            if Visible:
              if Hachures:
                trace Hachurage(polygone(A[l][k],B[l][k],B[l][k]+unitex*(LargB,0),A[l][k]+unitex*(LargB,0)),15+(l-1)*(180/#3),0.15,0) withpen pencircle scaled Epaisseur;
                trace polygone(A[l][k],B[l][k],B[l][k]+unitex*(LargB,0),A[l][k]+unitex*(LargB,0))withpen pencircle scaled Epaisseur;
              else:
                fill polygone(A[l][k],B[l][k],B[l][k]+unitex*(LargB,0),A[l][k]+unitex*(LargB,0)) withcolor Coul[l];
                trace polygone(A[l][k],B[l][k],B[l][k]+unitex*(LargB,0),A[l][k]+unitex*(LargB,0));
              fi;
            fi;
          fi;
        endfor;
      endfor;
      %%%%%%%% Affichage des données ou pas
      if DonneesSup:
        for k=1 upto nbdonnees:
          for l=1 upto #3-1:
            NumOrd:=k+nbdonnees*(l-1);
            if Vide=false:
              if DessinVide:
                TestVisibilite(NumOrd);
              fi;
              if Visible:
                label(TEX("\num{"&decimal(OrdV[NumOrd])&"}"),iso(A[l][k],B[l][k]+unitex*(LargB,0)));
              fi;
            fi;
          endfor;
        endfor;
      fi;
      %%%%%%%% Axes et labelisation
      if Hachures:
        drawoptions(withpen pencircle scaled Epaisseur);
      fi;
      drawarrow (0,0)--unitex*(maxx+1,0);
      if SansAxeOrd=false:
        drawarrow (0,0)--unitey*(0,ceiling(maxy/Pasy)*Pasy);
      fi;
      drawoptions();
      nb:=0;
      for p_=#1:
        nb:=nb+1;
        label.bot(TEX(p_),1/2[A[1][nb],A[1][nb]+unitex*(LargB,0)]);
      endfor;
      picture RetiensPicture;
      RetiensPicture=currentpicture;
      label.bot(TEX("\useKV[StatMulti]{LegendeX}"),iso((0,ypart(llcorner RetiensPicture)),lrcorner RetiensPicture));
      label.lft(TEX("\useKV[StatMulti]{LegendeY}") rotated 90,iso(llcorner RetiensPicture,ulcorner RetiensPicture));
      label.top(TEX("\useKV[StatMulti]{Titre}"),iso(ulcorner RetiensPicture,urcorner RetiensPicture));
      %%%%%%%% Legende des couleurs
      n:=0;
      if LegendesH:
        for p_=#5:
          n:=n+1;
          if Hachures:
            trace Hachurage((unitsquare xscaled 3mm yscaled 6mm) shifted(((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0,-1)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0)),15+(n-1)*(180/#3),0.15,0) withpen pencircle scaled Epaisseur;
            trace (unitsquare xscaled 3mm yscaled 6mm) shifted(((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0,-1)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0)) withpen pencircle scaled Epaisseur;
          else:
            fill (unitsquare scaled 3mm) shifted(((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0,-1)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0)) withcolor Coul[n];
            trace (unitsquare scaled 3mm) shifted(((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0,-1)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0));
          fi;
          label.rt(TEX(p_),((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0.3,-0.85)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0));
        endfor;
      else:
        for p_=#5:
          n:=n+1;
          if Hachures:
            trace Hachurage((unitsquare xscaled 6mm yscaled 3mm) shifted(urcorner RetiensPicture+5mm*(1,-n)) ,15+(n-1)*(180/#3),0.15,0) withpen pencircle scaled Epaisseur;
            trace (unitsquare xscaled 6mm yscaled 3mm) shifted(urcorner RetiensPicture+5mm*(1,-n)) withpen pencircle scaled Epaisseur;
            label.rt(TEX(p_),urcorner RetiensPicture+5mm*(2.4,-0.75-(n-1)));
          else:
            fill (unitsquare scaled 3mm) shifted(urcorner RetiensPicture+5mm*(1,-n)) withcolor Coul[n];
            trace (unitsquare scaled 3mm) shifted(urcorner RetiensPicture+5mm*(1,-n));
            label.rt(TEX(p_),urcorner RetiensPicture+5mm*(1.5,-0.75-(n-1)));
          fi;
        endfor;
      fi;  
    \end{mplibcode}%
}%

\NewDocumentCommand\BuildMPStatMultiBatons{mmmmmm}{%
  % #1 les labels des abscisses
  % #2 la liste des ordonnées
  % #3 le nombre de valeurs par abscisse
  % #4 les couleurs
  % #5 les légendes
  % #6 les numéros des rectangles à ne pas tracer : Attention à ne pas oublier que les rectangles sont construits par couleur et non de gauche à droite.
  \mplibforcehmode%
  \begin{mplibcode}
    defaultcolormodel := \useKV[ClesStat]{ModeleCouleur};
    % 
    \MPStatMultiNewCode
    % 
    vardef TestVisibilite(expr nb)=
      Visible:=true;
      op:=0;
      for l_=#6:
        if l_=nb:
          op:=op+1;
        fi;
      endfor;
      if op>0:
        Visible:=false;
      fi;
    enddef;
    % On détermine le décalage max en abscisse.
    nbdonnees=0;
    for l_=#1:
      nbdonnees:=nbdonnees+1;
    endfor;
    maxx:=nbdonnees;
    maxy:=max(#2);
    % 
    % On récupère les ordonnées
    RecuperationOrdo(#2);
    % on récupère les couleurs
    color Coul[];
    for k=1 upto #3:
      Coul[k]=CoulDefaut;
    endfor;
    n:=0;
    for p_=#4:
      n:=n+1;
      if color p_:
        Coul[n]:=p_;
      fi;
    endfor;
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
    if Grille:
      drawoptions(withcolor 0.75white);
      for k=0 step PasGrilley until ceiling(maxy/Pasy)*Pasy:
        trace (0,k*unitey)--(unitex*(maxx+1),k*unitey);
      endfor;
      drawoptions();
    fi;
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Tracé et remplissage %%%%%%%%%%%%%%%
    %%%%%%%% définition des points et tracés des polygones.
    for k=1 upto nbdonnees:
      for l=1 upto #3-1:
        NumOrd:=k+nbdonnees*(l-1);
        A[l][k]=(0.5*unitex,0) shifted ((k-1)*unitex,0);
        B[l][k]=A[l][k]+unitey*(0,Ord[NumOrd]);
      endfor;
    endfor;
    if Vide=false:  
    for k=1 upto nbdonnees:
      maxb:=1;
      for l=2 upto #3-1:
        if ypart(B[l][k])>ypart(B[l-1][k]):
          maxb:=l;
        fi;
      endfor;
      draw (A[1][k]--B[maxb][k]) dashed evenly;  
    endfor;
    for l=1 upto #3-1:
     draw B[l][1] for k=2 upto nbdonnees:
%          %NumOrd:=k+nbdonnees*(l-1);
%          %if Vide=false:
%          %  if DessinVide:
%          %    TestVisibilite(NumOrd);
%          %  fi;
%          %  if Visible:
%          %    
%          %  fi;
%          %  fi;
      --B[l][k]
      endfor withpen pencircle scaled 1.25 withcolor Coul[l];
    endfor;
    for k=1 upto nbdonnees:
      for l=1 upto #3-1:
        fill cercles(B[l][k],0.5mm) withcolor white;%
        trace cercles(B[l][k],0.5mm);
      endfor;
    endfor;
    fi;
      %%%%%%%% Affichage des données ou pas
      if DonneesSup:
        for k=1 upto nbdonnees:
          for l=1 upto #3-1:
            NumOrd:=k+nbdonnees*(l-1);
            if Vide=false:
              if DessinVide:
                TestVisibilite(NumOrd);
              fi;
              if Visible:
                label.urt(TEX("\footnotesize\num{"&decimal(Ord[NumOrd])&"}"),B[l][k]);
              fi;
            fi;
          endfor;
        endfor;
      fi;
      %%%%%%%% "Graduations" x
%      for k=0 upto nbdonnees-1:
%        drawoptions(shifted (k*unitex*(EcartB,0)));
%        trace (0.5*unitex,-1pt)--(0.5*unitex,1pt);
%        for l=1 upto #3-1:
%          trace (0.5*unitex,-1pt)--(0.5*unitex,1pt);
%        endfor;
%        drawoptions();
%      endfor;
      %%%%%%%% Graduations y
      for k=0 step Pasy until ceiling(maxy/Pasy)*Pasy:
        if GrandNombrey:
          label.lft(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreO}*"&decimal(k+Depart)&"}}"),(0,k*unitey));
        else:
          label.lft(TEX("\num{"&decimal(k+Depart)&"}"),(0,k*unitey));
        fi;
        if Tiret:
          trace (1pt,k*unitey)--(-1pt,k*unitey);
        else:
          fill cercles((0,k*unitey),1pt);
        fi;
      endfor;
      %%%%%%%% Axes et labelisation
%      if Hachures:
%        drawoptions(withpen pencircle scaled Epaisseur);
%      fi;
      drawarrow (0,0)--unitex*(maxx+1,0);
      if SansAxeOrd=false:
        drawarrow (0,0)--unitey*(0,ceiling(maxy/Pasy)*Pasy);
      fi;
      drawoptions();
      nb:=0;
      for p_=#1:
        nb:=nb+1;
        label.bot(TEX(p_),A[1][nb]);%,A[#3-1][nb]+unitex*(LargB,0)]);
      endfor;
      picture RetiensPicture;
      RetiensPicture=currentpicture;
      label.bot(TEX("\useKV[StatMulti]{LegendeX}"),iso(llcorner RetiensPicture,lrcorner RetiensPicture));
      label.lft(TEX("\useKV[StatMulti]{LegendeY}") rotated 90,iso(llcorner RetiensPicture,ulcorner RetiensPicture));
      label.top(TEX("\useKV[StatMulti]{Titre}"),iso(ulcorner RetiensPicture,urcorner RetiensPicture));
      %%%%%%%% Legende des couleurs
      n:=0;
      if LegendesH:
        for p_=#5:
          n:=n+1;
          if Hachures:
            trace Hachurage((unitsquare xscaled 3mm yscaled 6mm) shifted(((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0,-1)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0)),15+(n-1)*(180/#3),0.15,0) withpen pencircle scaled Epaisseur;
            trace (unitsquare xscaled 3mm yscaled 6mm) shifted(((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0,-1)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0)) withpen pencircle scaled Epaisseur;
          else:
            fill (unitsquare scaled 3mm) shifted(((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0,-1)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0)) withcolor Coul[n];
            trace (unitsquare scaled 3mm) shifted(((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0,-1)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0));
          fi;
          label.rt(TEX(p_),((n-1)/(#3-1))[llcorner RetiensPicture,lrcorner RetiensPicture]+10mm*(0.3,-0.85)+(0.5*abs(llcorner RetiensPicture-lrcorner RetiensPicture)/(#3-1),0));
        endfor;
      else:
        for p_=#5:
          n:=n+1;
          if Hachures:
            trace Hachurage((unitsquare xscaled 6mm yscaled 3mm) shifted(urcorner RetiensPicture+5mm*(1,-n)) ,15+(n-1)*(180/#3),0.15,0) withpen pencircle scaled Epaisseur;
            trace (unitsquare xscaled 6mm yscaled 3mm) shifted(urcorner RetiensPicture+5mm*(1,-n)) withpen pencircle scaled Epaisseur;
            label.rt(TEX(p_),urcorner RetiensPicture+5mm*(2.4,-0.75-(n-1)));
          else:
            fill (unitsquare scaled 3mm) shifted(urcorner RetiensPicture+5mm*(1,-n)) withcolor Coul[n];
            trace (unitsquare scaled 3mm) shifted(urcorner RetiensPicture+5mm*(1,-n));
            label.rt(TEX(p_),urcorner RetiensPicture+5mm*(1.5,-0.75-(n-1)));
          fi;
        endfor;
      fi;
    \end{mplibcode}%
}%

\NewDocumentCommand\buildmoustache{}{%
  \ifemptyKV[ClesStat]{Aberration}{%
    \buildmoustacheMP{\DonneeMin,\QuartileUn,\Mediane,\QuartileTrois,\DonneeMax,\Moyenne}%
  }{%
    \edef\PfMLimiteQMin{\fpeval{\QuartileUn-\useKV[ClesStat]{Aberration}*(\QuartileTrois-\QuartileUn)}}%
    \edef\PfMLimiteQMax{\fpeval{\QuartileTrois+\useKV[ClesStat]{Aberration}*(\QuartileTrois-\QuartileUn)}}%
    \edef\ListeAberrants{}%
    \edef\NbAberrants{0}%
    \edef\NbNonAberrants{0}%
    \foreachitem\tricot\in\ListeComplete{%
      \xintifboolexpr{\ListeComplete[\tricotcnt,1]<\PfMLimiteQMin 'or' \ListeComplete[\tricotcnt,1]>\PfMLimiteQMax}{%
        \edef\NbAberrants{\fpeval{\NbAberrants+1}}%
        \edef\ListeAberrants{\ListeAberrants,\ListeComplete[\tricotcnt,1]}%
      }{%
        \edef\NbNonAberrants{\fpeval{\NbNonAberrants+1}}%
        \ifnum\NbNonAberrants=1\relax%
          \edef\ListeNonAberrants{\ListeComplete[\tricotcnt,1]}%
        \else%
          \edef\ListeNonAberrants{\ListeNonAberrants,\ListeComplete[\tricotcnt,1]}%
        \fi%
      }%
    }%
    \ifnum\NbAberrants>0\relax%
      \buildmoustacheMPAber{\fpeval{min(\ListeNonAberrants)},\QuartileUn,\Mediane,\QuartileTrois,\fpeval{max(\ListeNonAberrants)},\Moyenne}{\ListeAberrants}%
    \else%
      \buildmoustacheMP{\DonneeMin,\QuartileUn,\Mediane,\QuartileTrois,\DonneeMax,\Moyenne}%
    \fi%
  }
}%

\NewDocumentCommand\buildmoustacheMP{m}{%
  \setbox1=\hbox{,}%
  \mplibforcehmode%
  \begin{mplibcode}
    pasx=\useKV[ClesStat]{Pasx};
    PasGrillex=\useKV[ClesStat]{PasGrillex};
    PasGrilley=\useKV[ClesStat]{PasGrilley};
    u:=u/pasx;
    boolean Lecture,Vide,IQR,Vertical,AvecMoyenne,Cours;
    Lecture=\useKV[ClesStat]{Lecture};
    Vide=\useKV[ClesStat]{Vide};
    IQR=\useKV[ClesStat]{IQR};
    Vertical=\useKV[ClesStat]{Vertical};
    AvecMoyenne=\useKV[ClesStat]{AvecMoyenne};
    Cours=\useKV[ClesStat]{Cours};
    %min/q1/med/q2/max
    vardef LectureDonnees(text t)=
      n:=0;
      for p_=t:
        n:=n+1;
        val[n]=p_;
      endfor;
    enddef;
    
    vardef TraceMoustache=
      save PfC;
      picture PfC;
      pair P[];
      P1=(u*val1,1cm);
      P2=(u*val2,1cm);
      P3=(u*val3,1cm);
      P4=(u*val4,1cm);
      P5=(u*val5,1cm);
      P6=(u*val6,1cm);%Moyenne
      PfC=image(
      for k=1 upto 5:
        if (k>1) and (k<5):
          if Lecture:
            trace segment((xpart(P[k]),0.5cm),(xpart(P[k]),0)) dashed evenly;
            label.top(TEX("\rule[-\dp1]{0pt}{0pt}\scriptsize\num{"&decimal(val[k])&"}"),(xpart(P[k]),1.5cm));
          fi;
        else:
          if Lecture:
            trace segment(P[k],(xpart(P[k]),0)) dashed evenly;
            label.top(TEX("\rule[-\dp1]{0pt}{0pt}\scriptsize\num{"&decimal(val[k])&"}"),(xpart(P[k]),1.2cm));
          fi;
        fi;
      endfor;
      trace marquesegment(P1,P5);
      trace polygone(P2+(0,-(5 + (PasGrilley div 2))*1mm),P4+(0,-(5 + (PasGrilley div 2))*1mm),P4+(0,(5 + (PasGrilley div 2))*1mm),P2+(0,5 + (PasGrilley div 2))*1mm);
      trace segment(P3+(0,-(5 + (PasGrilley div 2))*1mm),P3+(0,(5 + (PasGrilley div 2))*1mm));
      trace segment(P1,P2);
      trace segment(P4,P5);
      if AvecMoyenne:
        fill (unitsquare scaled 1.5mm) shifted (P6-center (unitsquare scaled 1.5mm));
        trace segment(P6+(0,-(5 + (PasGrilley div 2))*1mm),P6+(0,(5 + (PasGrilley div 2))*1mm)) dashed evenly;
      fi;
      if IQR:
        trace (xpart(P[2]),0)--(xpart(P[2]),-5mm) withcolor 0.8white;
        trace (xpart(P[4]),0)--(xpart(P[4]),-5mm) withcolor 0.8white;
        drawdblarrow (xpart(P[2]),-5mm)--(xpart(P[4]),-5mm);
        label.bot(TEX("IQR"),iso((xpart(P[2]),-5mm),(xpart(P[4]),-5mm)));
      fi;
      if Cours:
        trace (xpart(P[1]),0)--(xpart(P[1]),-5mm) withcolor 0.8white;
        trace (xpart(P[3]),0)--(xpart(P[3]),-5mm) withcolor 0.8white;
        trace (xpart(P[5]),0)--(xpart(P[5]),-5mm) withcolor 0.8white;
        trace segment(P2+(0,(5 + (PasGrilley div 2))*1mm),P2+(0,(15 + (PasGrilley div 2))*1mm)) withcolor 0.8white;
        trace segment(P4+(0,(5 + (PasGrilley div 2))*1mm),P4+(0,(15 + (PasGrilley div 2))*1mm)) withcolor 0.8white;
        label.bot(TEX("\footnotesize Minimum"),(xpart(P[1]),-5mm));
        label.bot(TEX("\footnotesize Médiane"),(xpart(P[3]),-5mm));
        label.bot(TEX("\footnotesize Maximum"),(xpart(P[5]),-5mm));
        label.top(TEX("\footnotesize $Q_1$"),P2+(0,(15 + (PasGrilley div 2))*1mm));
        label.top(TEX("\footnotesize $Q_3$"),P4+(0,(15 + (PasGrilley div 2))*1mm));        
      fi;
      );
      PfC
    enddef;

    vardef TraceMoustacheVer=
      save PfCver;
      picture PfCver;
      pair P[];
      P1=(1cm,u*val1);
      P2=(1cm,u*val2);
      P3=(1cm,u*val3);
      P4=(1cm,u*val4);
      P5=(1cm,u*val5);
      P6=(1cm,u*val6);
      PfCver=image(
      if IQR:
        trace (P[2]+((5 + (PasGrilley div 2))*1mm,0))--(P[2]+((18 + (PasGrilley div 2))*1mm,0)) withcolor 0.8white;
        trace (P[4]+((5 + (PasGrilley div 2))*1mm,0))--(P[4]+((18 + (PasGrilley div 2))*1mm,0)) withcolor 0.8white;
        drawdblarrow (P[2]+((18 + (PasGrilley div 2))*1mm,0))--(P[4]+((18 + (PasGrilley div 2))*1mm,0));
        label.rt(TEX("IQR"),iso(P[2]+((18 + (PasGrilley div 2))*1mm,0),P[4]+((18 + (PasGrilley div 2))*1mm,0)));
      fi;
      for k=1 upto 5:
        if (k>1) and (k<5):
          if Lecture:
            trace segment((0.5cm,ypart(P[k])),(0,ypart(P[k]))) dashed evenly;
            label.rt(TEX("\scriptsize\num{"&decimal(val[k])&"}"),P[k]+((5 + (PasGrilley div 2))*1mm,0));
          fi;
        else:
          if Lecture:
            trace segment(P[k],(0,ypart(P[k]))) dashed evenly;
            label.rt(TEX("\scriptsize\num{"&decimal(val[k])&"}"),P[k]+((2 + (PasGrilley div 2))*1mm,0));
          fi;
        fi;
      endfor;
      trace marquesegment(P1,P5);
      trace polygone(%
      P2+(-(5 + (PasGrilley div 2))*1mm,0),%
      P4+(-(5 + (PasGrilley div 2))*1mm,0),%
      P4+((5 + (PasGrilley div 2))*1mm,0),%
      P2+((5 + (PasGrilley div 2))*1mm,0)%
      );
      trace segment(P3+(-(5 + (PasGrilley div 2))*1mm,0),P3+((5 + (PasGrilley div 2))*1mm,0));
      trace segment(P1,P2);
      trace segment(P4,P5);
      if AvecMoyenne:
        fill (unitsquare scaled 1.5mm) shifted (P6-center (unitsquare scaled 1.5mm));
        trace segment(P6+(-(5 + (PasGrilley div 2))*1mm,0),P6+((5 + (PasGrilley div 2))*1mm,0)) dashed evenly;
      fi;
      );
      PfCver
    enddef;

    LectureDonnees(#1);

    %%% Fond
    pair R[];
    debordmin=pasx;
    debordmax=pasx;
    if Vertical:
      R1=(0,u*(floor((val1-debordmin)/pasx)*pasx));
      R2=(0,u*(ceiling((val5+debordmax)/pasx)*pasx));
      % 
      for k=0 upto 24/PasGrilley:
        draw (R1--R2) shifted (k*PasGrilley*1mm,0) withcolor 0.8white;
      endfor;
      k=0;
      forever:exitif k>ypart(R2-R1);
        draw (R1--(R1+(2.4cm,0))) shifted(0,k) withcolor 0.8white;
        k:=k+PasGrillex*1mm;
      endfor;
      for k=0 step pasx until ((ceiling((val5+debordmax)/pasx)*pasx-(floor((val1-debordmin)/pasx)*pasx))):
        draw (R1+(-0.5mm,k*u))--(R1+(0.5mm,k*u));
        label.lft(decimal(floor((val1-debordmin+k)/pasx)*pasx),R1+k*(0,u));
      endfor;
      draw R1--R2;  
      % 
      if Vide=false:
        draw TraceMoustacheVer;
      fi;
    else:
      R1=(u*(floor((val1-debordmin)/pasx)*pasx),0);
      R2=(u*(ceiling((val5+debordmax)/pasx)*pasx),0);
      % 
      for k=0 upto 20/PasGrilley:
        draw (R1--R2) shifted (0,k*PasGrilley*1mm) withcolor 0.8white;
      endfor;
      k=0;
      forever:exitif k>xpart(R2-R1);
        draw (R1--(R1+(0,2cm))) shifted(k,0) withcolor 0.8white;
        k:=k+PasGrillex*1mm;
      endfor;
      for k=0 step pasx until ((ceiling((val5+debordmax)/pasx)*pasx-(floor((val1-debordmin)/pasx)*pasx))):
        draw (R1+(k*u,-0.5mm))--(R1+(k*u,0.5mm));
        label.bot(decimal(floor((val1-debordmin+k)/pasx)*pasx),R1+k*(u,0));
      endfor;
      draw R1--R2;  
      % 
      if Vide=false:
        draw TraceMoustache;
      fi;
    fi;
  \end{mplibcode}%
}%

\NewDocumentCommand\buildmoustacheMPAber{mm}{%
  \setbox1=\hbox{,}%
  \mplibforcehmode%
  \begin{mplibcode}
    pasx=\useKV[ClesStat]{Pasx};
    PasGrillex=\useKV[ClesStat]{PasGrillex};
    PasGrilley=\useKV[ClesStat]{PasGrilley};
    u:=u/pasx;
    boolean Lecture,Vide,IQR,Vertical,AvecMoyenne;
    Lecture=\useKV[ClesStat]{Lecture};
    Vide=\useKV[ClesStat]{Vide};
    IQR=\useKV[ClesStat]{IQR};
    Vertical=\useKV[ClesStat]{Vertical};
    AvecMoyenne=\useKV[ClesStat]{AvecMoyenne};
    %min/q1/med/q2/max
    vardef LectureDonnees(text t)=
      n:=0;
      for p_=t:
        n:=n+1;
        val[n]=p_;
      endfor;
    enddef;

    mingrille=val1;
    maxgrille=val5;
    
    vardef LectureAberrants(text t)=
      n:=0;
      for p_=t:
        n:=n+1;
        valAber[n]=p_;
        if valAber[n]<val1:
          mingrille:=valAber[n];
        fi;
        if valAber[n]>val5:
          maxgrille:=valAber[n];
        fi;
      endfor;
      TotalAber=n;  
    enddef;
    
    vardef TraceMoustache=
      save PfC;
      picture PfC;
      pair P[],Q[];
      P1=(u*val1,1cm);
      P2=(u*val2,1cm);
      P3=(u*val3,1cm);
      P4=(u*val4,1cm);
      P5=(u*val5,1cm);
      P6=(u*val6,1cm);%Moyenne
      for q=1 upto TotalAber:
        Q[q]=(u*valAber[q],1cm);
      endfor;
      PfC=image(
      for k=1 upto 5:
        if (k>1) and (k<5):
          if Lecture:
            trace segment((xpart(P[k]),0.5cm),(xpart(P[k]),0)) dashed evenly;
            label.top(TEX("\rule[-\dp1]{0pt}{0pt}\scriptsize\num{"&decimal(val[k])&"}"),(xpart(P[k]),1.5cm));
          fi;
        else:
          if Lecture:
            trace segment(P[k],(xpart(P[k]),0)) dashed evenly;
            label.top(TEX("\rule[-\dp1]{0pt}{0pt}\scriptsize\num{"&decimal(val[k])&"}"),(xpart(P[k]),1.2cm));
          fi;
        fi;
      endfor;
      trace marquesegment(P1,P5);
      trace polygone(P2+(0,-(5 + (PasGrilley div 2))*1mm),P4+(0,-(5 + (PasGrilley div 2))*1mm),P4+(0,(5 + (PasGrilley div 2))*1mm),P2+(0,5 + (PasGrilley div 2))*1mm);
      trace segment(P3+(0,-(5 + (PasGrilley div 2))*1mm),P3+(0,(5 + (PasGrilley div 2))*1mm));
      trace segment(P1,P2);
      trace segment(P4,P5);
      if AvecMoyenne:
        fill (unitsquare scaled 1.5mm) shifted (P6-center (unitsquare scaled 1.5mm));
        trace segment(P6+(0,-(5 + (PasGrilley div 2))*1mm),P6+(0,(5 + (PasGrilley div 2))*1mm)) dashed evenly;
      fi;
      if IQR:
        trace (xpart(P[2]),0)--(xpart(P[2]),-5mm) withcolor 0.8white;
        trace (xpart(P[4]),0)--(xpart(P[4]),-5mm) withcolor 0.8white;
        drawdblarrow (xpart(P[2]),-5mm)--(xpart(P[4]),-5mm);
        label.bot(TEX("IQR"),iso((xpart(P[2]),-5mm),(xpart(P[4]),-5mm)));
      fi;
      v:=u;
      u:=5mm;
      marque_p:="croix";
      for q=1 upto TotalAber:
      pointe(Q[q]);
      endfor;
      u:=v;
      );
      PfC
    enddef;

    vardef TraceMoustacheVer=
      save PfCver;
      picture PfCver;
      pair P[],Q[];
      P1=(1cm,u*val1);
      P2=(1cm,u*val2);
      P3=(1cm,u*val3);
      P4=(1cm,u*val4);
      P5=(1cm,u*val5);
      P6=(1cm,u*val6);
      for q=1 upto TotalAber:
        Q[q]=(1cm,u*valAber[q]);
      endfor;
      PfCver=image(
      if IQR:
        trace (P[2]+((5 + (PasGrilley div 2))*1mm,0))--(P[2]+((18 + (PasGrilley div 2))*1mm,0)) withcolor 0.8white;
        trace (P[4]+((5 + (PasGrilley div 2))*1mm,0))--(P[4]+((18 + (PasGrilley div 2))*1mm,0)) withcolor 0.8white;
        drawdblarrow (P[2]+((18 + (PasGrilley div 2))*1mm,0))--(P[4]+((18 + (PasGrilley div 2))*1mm,0));
        label.rt(TEX("IQR"),iso(P[2]+((18 + (PasGrilley div 2))*1mm,0),P[4]+((18 + (PasGrilley div 2))*1mm,0)));
      fi;
      for k=1 upto 5:
        if (k>1) and (k<5):
          if Lecture:
            trace segment((0.5cm,ypart(P[k])),(0,ypart(P[k]))) dashed evenly;
            label.rt(TEX("\scriptsize\num{"&decimal(val[k])&"}"),P[k]+((5 + (PasGrilley div 2))*1mm,0));
          fi;
        else:
          if Lecture:
            trace segment(P[k],(0,ypart(P[k]))) dashed evenly;
            label.rt(TEX("\scriptsize\num{"&decimal(val[k])&"}"),P[k]+((2 + (PasGrilley div 2))*1mm,0));
          fi;
        fi;
      endfor;
      trace marquesegment(P1,P5);
      trace polygone(%
      P2+(-(5 + (PasGrilley div 2))*1mm,0),%
      P4+(-(5 + (PasGrilley div 2))*1mm,0),%
      P4+((5 + (PasGrilley div 2))*1mm,0),%
      P2+((5 + (PasGrilley div 2))*1mm,0)%
      );
      trace segment(P3+(-(5 + (PasGrilley div 2))*1mm,0),P3+((5 + (PasGrilley div 2))*1mm,0));
      trace segment(P1,P2);
      trace segment(P4,P5);
      if AvecMoyenne:
        fill (unitsquare scaled 1.5mm) shifted (P6-center (unitsquare scaled 1.5mm));
        trace segment(P6+(-(5 + (PasGrilley div 2))*1mm,0),P6+((5 + (PasGrilley div 2))*1mm,0)) dashed evenly;
      fi;
      v:=u;
      u:=5mm;
      marque_p:="croix";
      for q=1 upto TotalAber:
        pointe(Q[q]);
      endfor;
      u:=v;  
      );
      PfCver
    enddef;

    LectureDonnees(#1);
    LectureAberrants(#2);
    
    %%% Fond
    pair R[];
    if Vertical:
      R1=(0,u*(floor(mingrille/pasx)*pasx));
      R2=(0,u*(ceiling(maxgrille/pasx)*pasx));
      % 
      for k=0 upto 24/PasGrilley:
        draw (R1--R2) shifted (k*PasGrilley*1mm,0) withcolor 0.8white;
      endfor;
      k=0;
      forever:exitif k>ypart(R2-R1);
        draw (R1--(R1+(2.4cm,0))) shifted(0,k) withcolor 0.8white;
        k:=k+PasGrillex*1mm;
      endfor;
      for k=0 step pasx until ((ceiling(maxgrille/pasx)*pasx-(floor(mingrille/pasx)*pasx))):
        draw (R1+(-0.5mm,k*u))--(R1+(0.5mm,k*u));
        label.lft(decimal(floor((mingrille+k)/pasx)*pasx),R1+k*(0,u));
      endfor;
      draw R1--R2;  
      % 
      if Vide=false:
        draw TraceMoustacheVer;
      fi;
    else:
      R1=(u*(floor(mingrille/pasx)*pasx),0);
      R2=(u*(ceiling(maxgrille/pasx)*pasx),0);
      % 
      for k=0 upto 20/PasGrilley:
        draw (R1--R2) shifted (0,k*PasGrilley*1mm) withcolor 0.8white;
      endfor;
      k=0;
      forever:exitif k>xpart(R2-R1);
        draw (R1--(R1+(0,2cm))) shifted(k,0) withcolor 0.8white;
        k:=k+PasGrillex*1mm;
      endfor;
      for k=0 step pasx until ((ceiling(maxgrille/pasx)*pasx-(floor(mingrille/pasx)*pasx))):
        draw (R1+(k*u,-0.5mm))--(R1+(k*u,0.5mm));
        label.bot(decimal(floor((mingrille+k)/pasx)*pasx),R1+k*(u,0));
      endfor;
      draw R1--R2;  
      % 
      if Vide=false:
        draw TraceMoustache;
      fi;
    fi;
  \end{mplibcode}%
}%

\makeatletter
\NewDocumentCommand\StatNuage{om}{%
  \useKVdefault[ClesStat]%
  \setKV[ClesStat]{#1}%
  \toklistepoint{}%
  \edef\PfC@ListePointsAPlacer{#2}%
  \setsepchar[*]{,*/}\ignoreemptyitems%
  \readlist*\PfC@ListeNuagePoints{\PfC@ListePointsAPlacer}%
  \reademptyitems%
  \foreachitem\compteur\in\PfC@ListeNuagePoints{%
    \expandafter\Updatetoks\compteur\nil%
  }%
  \PfC@MPStatNuage{\the\toklistepoint}%
}%

\def\PfCMPStatNuageCode{%
  maxx:=-4095;
  maxy:=-4095;
  unitex:=\useKV[ClesStat]{Unitex}*cm;
  unitey:=\useKV[ClesStat]{Unitey}*cm;
  boolean Lecture,LectureFine,AideLecture,DonneesSup,Reponses,Tiret,GrandNombrex,GrandNombrey,Grille,Relie,Codes,Pointe,Titre;
  GrandNombrex=\useKV[ClesStat]{GrandNombrex};
  GrandNombrey=\useKV[ClesStat]{GrandNombrey};
  if GrandNombrex:
    GrandNombreA=\useKV[ClesStat]{GrandNombreA};
  fi;
  if GrandNombrey:
    GrandNombreO=\useKV[ClesStat]{GrandNombreO};
  fi;
  %
  \ifemptyKV[ClesStat]{AngleRotationAbscisse}{AngleRotation=0;}{AngleRotation=\useKV[ClesStat]{AngleRotationAbscisse};}
  %
  Titre:=\useKV[ClesStat]{Titre};  
  Lecture=\useKV[ClesStat]{Lecture};
  LectureFine=\useKV[ClesStat]{LectureFine};
  AideLecture=\useKV[ClesStat]{AideLecture};
  DonneesSup=\useKV[ClesStat]{DonneesSup};
  Reponses=\useKV[ClesStat]{Reponses};
  Codes=\useKV[ClesStat]{Codes};
  Pointe=\useKV[ClesStat]{Pointe};
  Tiret=\useKV[ClesStat]{Tiret};
  Grille:=\useKV[ClesStat]{Grille};
  Pasx:=\useKV[ClesStat]{Pasx};
  Pasy:=\useKV[ClesStat]{Pasy};
  PasGrillex:=\useKV[ClesStat]{PasGrillex};
  PasGrilley:=\useKV[ClesStat]{PasGrilley};
  PasGradx:=\useKV[ClesStat]{PasGradx};
  PasGrady:=\useKV[ClesStat]{PasGrady};
  color CoulDefaut;
  CoulDefaut=\useKV[ClesStat]{CouleurDefaut};
  Depart=\useKV[ClesStat]{Depart};
  xpartorigine:=\useKV[ClesStat]{Origine};
  %
  pair A[],B[],P[];
  vardef toto(text t)=
    n:=0;
    for p_=t:
      if pair p_:
        n:=n+1;
        P[n]=((xpart(p_)-(xpartorigine))*unitex,(ypart(p_)-Depart)*unitey);
        if xpart(p_)>maxx:
          maxx:=xpart(p_);
        fi;
        if ypart(p_)>maxy:
          maxy:=ypart(p_);
        fi;
        A[n]=unitex*(xpart(p_)-(xpartorigine),0);
        B[n]=unitey*(0,ypart(p_)-(Depart));
      fi;
    endfor;
    %label.urt(decimal(xpartorigine),(0,0));  
    maxx:=((maxx-(xpartorigine)) div PasGradx + 1)*PasGradx;
    maxAxex:=maxx if PasGradx<>1:if (maxx mod PasGradx)>0:+PasGradx fi; else:+1 fi;
    %alpha=floor(PasGrady/PasGrilley);
    maxy:=maxy-Depart;
    if DonneesSup:
      maxAxey:=(ceiling(maxy/Pasy)+1)*Pasy;%
    else:
      maxAxey:=((maxy div PasGrady)+1)*PasGrady;%(floor((ceiling(maxy) div (alpha)+1)*alpha) div PasGrady)*PasGrady;%(floor(Depart+(ceiling(maxy) div (alpha)+1)*alpha) div PasGrady)*PasGrady-Depart;
    fi;
    %label.ulft(decimal(maxAxey),(0,0));  
  enddef;
}

% Construction du nuage de points
\newcommand\PfC@MPStatNuage[1]{%
  \mplibforcehmode%
  \begin{mplibcode}
    defaultcolormodel := \useKV[ClesStat]{ModeleCouleur};
    %
    \PfCMPStatNuageCode
    %
    vardef tata(text t)=%
      l=0;
      for p_=t:
        if pair p_:
          l:=l+1;
          if GrandNombrex:
            label.bot(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreA}*"&decimal(xpart(p_))&"}}") rotated AngleRotation,A[l]);
          else:
            label.bot(TEX("\num{"&decimal(xpart(p_))&"}") rotated AngleRotation,A[l]);
          fi;
        fi;
        if Tiret:
          trace (B[l]+(-1pt,0))--(B[l]+(1pt,0));
          label.lft(TEX("\num{"&decimal(p_)&"}"),B[l]);
        else:
          dotlabel.lft(TEX("\num{"&decimal(ypart(p_))&"}"),B[l]);
        fi;
      endfor;
    enddef;
    toto(#1);
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if Grille:
      drawoptions(withpen pencircle scaled 0.5 withcolor 0.75white);
      for k=0 step PasGrillex until maxAxex:
        trace (k*unitex,0)--(k*unitex,unitey*maxAxey*Pasy);
      endfor;
      for k=0 step PasGrilley until maxAxey*Pasy:
        trace (0,k*unitey)--(unitex*maxAxex,k*unitey);
      endfor;
      drawoptions(withpen pencircle scaled 0.8 withcolor 0.75white);
      for k=0 step 5*PasGrillex until maxAxex:
        trace (k*unitex,0)--(k*unitex,unitey*maxAxey*Pasy);
      endfor;
      for k=0 step 5*PasGrilley until maxAxey*Pasy:
        trace (0,k*unitey)--(unitex*maxAxex,k*unitey);
      endfor;  
      drawoptions(withpen pencircle scaled 1.1 withcolor 0.75white);
      for k=0 step 10*PasGrillex until maxAxex:
        trace (k*unitex,0)--(k*unitex,unitey*maxAxey*Pasy);
      endfor;
      for k=0 step 10*PasGrilley until maxAxey*Pasy:
        trace (0,k*unitey)--(unitex*maxAxex,k*unitey);
      endfor;
      drawoptions();
    fi;
    for k=1 upto n:
      if Pointe:
        trace (P[k]+(-0.5mm,-0.5mm))--(P[k]+(0.5mm,0.5mm));
        trace (P[k]+(0.5mm,-0.5mm))--(P[k]+(-0.5mm,0.5mm));
      else:
        dotlabel("",P[k]);
      fi;
      if AideLecture:
        draw B[k]--P[k] dashed evenly;
      fi;
    endfor;  
    if LectureFine:
      for k=0 step PasGrady until ((maxy+2*Pasy)):
        if Tiret:
          trace (1pt,k*unitey)--(-1pt,k*unitey);
          if GrandNombrey:
            label.lft(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreO}*"&decimal(k+Depart)&"}}"),(0,k*unitey));
          else:
            label.lft(TEX("\num{"&decimal(k+Depart)&"}"),(0,k*unitey));
          fi;
        else:
          if GrandNombrey:
            dotlabel.lft(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreO}*"&decimal(k+Depart)&"}}"),(0,k*unitey));
          else:
            dotlabel.lft(TEX("\num{"&decimal(k+Depart)&"}"),(0,k*unitey));
          fi;
        fi;
      endfor;
      for k=0 step PasGradx until ((maxx+1*Pasx)):
        if Tiret:
          trace (k*unitex,-1pt)--(k*unitex,1pt);
          if GrandNombrex:
            label.bot(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreA}*"&decimal(k+xpartorigine)&"}}"),(k*unitex,0));
          else:
            label.bot(TEX("\num{"&decimal(k+xpartorigine)&"}"),(k*unitex,0));
          fi;
        else:
          if GrandNombrex:
            dotlabel.bot(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreA}*"&decimal(k+xpartorigine)&"}}"),(k*unitex,0));
          else:
            dotlabel.bot(TEX("\num{"&decimal(k+xpartorigine)&"}"),(k*unitex,0));
          fi;
        fi;
      endfor;  
    fi;
    if Lecture:
      for k=0 step PasGrady until PasGrady:
        if Tiret:
          trace (1pt,k*unitey)--(-1pt,k*unitey);
          if GrandNombrey:
            label.lft(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreO}*"&decimal(k+Depart)&"}}"),(0,k*unitey));
          else:
            label.lft(TEX("\num{"&decimal(k+Depart)&"}"),(0,k*unitey));
          fi;
        else:
          if GrandNombrey:
            dotlabel.lft(TEX("\num{\fpeval{\useKV[ClesStat]{GrandNombreO}*"&decimal(k+Depart)&"}}"),(0,k*unitey));
          else:
            dotlabel.lft(TEX("\num{"&decimal(k+Depart)&"}"),(0,k*unitey));
          fi;
        fi;
      endfor;
    fi;
    drawarrow (0,0)--unitex*(maxx+2,0);
    drawarrow (0,0)--unitey*(0,maxAxey*Pasy+1);
    %
    if Titre:
      label.bot(TEX("\useKV[ClesStat]{Donnee}"),iso(lrcorner currentpicture,llcorner currentpicture)+unitey*(0,-0.5));
      label.lft(TEX("\useKV[ClesStat]{Effectif}"),iso(llcorner currentpicture,ulcorner currentpicture)+unitex*(-0.5,0));
    else:
      label.rt(TEX("\useKV[ClesStat]{Donnee}"),unitex*(maxx+2,0));
      label.urt(TEX("\useKV[ClesStat]{Effectif}"),unitey*(0,maxAxey*Pasy+1));
    fi;
    if Codes:
      \useKV[ClesStat]{Traces};
    fi;
  \end{mplibcode}%
}%
\makeatother