%%%
% Puissances 4
%%%
\setKVdefault[ClesPQuatre]{Couleur=Gray,Largeur=2cm,LargeurUn=2cm,Multiplication,Entier,Nombre,Exposant=false,Libre=false,Texte=false,Echelle=2}%
\defKV[ClesPQuatre]{Addition=\setKV[ClesPQuatre]{Multiplication=false}}%
\defKV[ClesPQuatre]{Relatif=\setKV[ClesPQuatre]{Entier=false}}%
\defKV[ClesPQuatre]{Puissance=\setKV[ClesPQuatre]{Exposant}}%
\defKV[ClesPQuatre]{Autre=\setKV[ClesPQuatre]{Nombre=false}\setKV[ClesPQuatre]{Libre}}%
\defKV[ClesPQuatre]{Consignes=\setKV[ClesPQuatre]{Texte}}%

\newtoks\toklistePQuatreh%
\newtoks\toklistePQuatrev%
\def\UpdatetoksPQuatreh#1\nil{\addtotok\toklistePQuatreh{"#1",}}%
\def\UpdatetoksPQuatrev#1\nil{\addtotok\toklistePQuatrev{"#1",}}%

\NewDocumentCommand\PQuatre{o +m}{%
  \useKVdefault[ClesPQuatre]%
  \toklistePQuatreh{}%
  \toklistePQuatrev{}%
  \setKV[ClesPQuatre]{#1}%
  \ifboolKV[ClesPQuatre]{Nombre}{%
    \ifboolKV[ClesPQuatre]{Exposant}{%
      \def\PQuatreListe{$10^{-10}$,$10^{-9}$,$10^{-8}$,$10^{-7}$,$10^{-6}$,$10^{-5}$,$10^{-4}$,$10^{-3}$,$10^{-2}$,$10^{2}$,$10^{3}$,$10^{4}$,$10^{5}$,$10^{6}$,$10^{7}$,$10^{8}$,$10^{9}$,$10^{10}$}%
      \MelangeListe{\PQuatreListe}{7}%
      \readlist*\PQuatreListeH{\faa}%
      \MelangeListe{\PQuatreListe}{7}%
      \readlist*\PQuatreListeV{\faa}%
      \foreachitem\compteur\in\PQuatreListeH{\expandafter\UpdatetoksPQuatreh\compteur\nil}%
      \foreachitem\compteur\in\PQuatreListeV{\expandafter\UpdatetoksPQuatrev\compteur\nil}%
    }{%
      \ifboolKV[ClesPQuatre]{Entier}{%
        % On choisit aléatoirement les listes de nombres de 2 à 10 en faisant deux listes : horizontale et verticale
        \def\PQuatreListe{2,3,4,5,6,7,8,9,10}%
        \MelangeListe{\PQuatreListe}{7}%
        \readlist*\PQuatreListeH{\faa}%
        \MelangeListe{\PQuatreListe}{7}%
        \readlist*\PQuatreListeV{\faa}%
        \foreachitem\compteur\in\PQuatreListeH{\expandafter\UpdatetoksPQuatreh\compteur\nil}%
        \foreachitem\compteur\in\PQuatreListeV{\expandafter\UpdatetoksPQuatrev\compteur\nil}%
      }{%
        % On choisit aléatoirement les listes de nombres de -10 à -2 union 2 à 10 en faisant deux listes : horizontale et verticale
        \def\PQuatreListe{$-10$,$-9$,$-8$,$-7$,$-6$,$-5$,$-4$,$-3$,$-2$,2,3,4,5,6,7,8,9,10}%
        \MelangeListe{\PQuatreListe}{7}%
        \readlist*\PQuatreListeH{\faa}%
        \MelangeListe{\PQuatreListe}{7}%
        \readlist*\PQuatreListeV{\faa}%
        \foreachitem\compteur\in\PQuatreListeH{\expandafter\UpdatetoksPQuatreh\compteur\nil}%
        \foreachitem\compteur\in\PQuatreListeV{\expandafter\UpdatetoksPQuatrev\compteur\nil}%
      }%
    }%
  }{%
    % on lit la liste des données fournies par l'utilisateur
    \setsepchar[*]{,*/}%
    \readlist\PQuatreListes{#2}%
    \setsepchar{,}%
    \foreachitem\compteur\in\PQuatreListes[1]{\expandafter\UpdatetoksPQuatrev\compteur\nil}%
    \foreachitem\compteur\in\PQuatreListes[2]{\expandafter\UpdatetoksPQuatreh\compteur\nil}%
  }%
  % Une fois les listes construites, on dessine et on place les listes.
  \PQuatreGrille{\the\toklistePQuatrev}{\the\toklistePQuatreh}%
}%

\NewDocumentCommand\PQuatreGrille{m m}{%
  \ifluatex%
  \mplibforcehmode%
  \begin{mplibcode}
    PQLargeur=\useKV[ClesPQuatre]{Largeur};
    PQLargeurUn=\useKV[ClesPQuatre]{LargeurUn};
    PQEchelle=\useKV[ClesPQuatre]{Echelle};
    color PQfond;
    PQfond=\useKV[ClesPQuatre]{Couleur};
    boolean PQLibre,PQMultiplication,PQTexte;
    PQLibre:=\useKV[ClesPQuatre]{Libre};
    PQMultiplication=\useKV[ClesPQuatre]{Multiplication};
    PQTexte:=\useKV[ClesPQuatre]{Texte};

    if PQTexte:
    string PQConsignes;
    PQConsignes=\useKV[ClesPQuatre]{Consignes};
    fi;
    
    % On calcule le nombre de cases
    nchauteur:=0;
    for p_=#1:
    nchauteur:=incr nchauteur;
    endfor;
    nclargeur:=0;
    for p_=#2:
    nclargeur:=incr nclargeur;
    endfor;
    if PQLibre=false:
    nchauteur:=7;
    nclargeur:=7;
    fi;
    %On affiche
    pair A,B,C,D,H[],V[],M[][];
    A=(0,0);
    B-A=PQLargeur*(nclargeur,0);
    C-B=PQLargeur*(0,nchauteur);
    D-C=A-B;
    fill polygone(A,B,C,D) withcolor PQfond;
    trace polygone(A,B,C,D);
    for k=0 upto (nclargeur-1):
    for l=0 upto (nchauteur-1):
    M[k][l]=A+0.5*(PQLargeur,PQLargeur)+k*(PQLargeur,0)+l*(0,PQLargeur);
    fill cercles(M[k][l],0.4*PQLargeur) withcolor blanc;
    trace cercles(M[k][l],0.4*PQLargeur);
    endfor;
    endfor;
    labeloffset:=labeloffset*2;
    if PQLibre:
    if PQTexte:
    label.llft(TEX("\begin{minipage}{"&decimal(PQLargeurUn)&"pt}"&PQConsignes&"\end{minipage}") scaled PQEchelle,A);
    fi;
    else:
    if PQMultiplication:
    label.llft(TEX("$\times$") scaled PQEchelle,A);
    else:
    label.llft(TEX("$+$") scaled PQEchelle,A);
    fi;
    fi;
    labeloffset:=labeloffset/2;
    vardef Vertical(text t)=
    n:=0;
    for p_=t:
    label.lft(TEX(p_) scaled PQEchelle,A+(0,n*PQLargeur+PQLargeur/2));
    n:=n+1;
    endfor;
    enddef;
    vardef Horizontal(text t)=
    n:=0;
    for p_=t:
    label.bot(TEX(p_) scaled PQEchelle,A+(n*PQLargeur+PQLargeur/2,0));
    n:=n+1;
    endfor;
    enddef;
    labeloffset:=labeloffset*4;
    Vertical(#1);
    Horizontal(#2);
  \end{mplibcode}
  \else%
  \begin{mpost}[mpsettings={Largeur=\useKV[ClesPQuatre]{Largeur};Largeur=\useKV[ClesPQuatre]{Largeur};LargeurUn=\useKV[ClesPQuatre]{LargeurUn};Echelle=\useKV[ClesPQuatre]{Echelle};color fond;fond=\useKV[ClesPQuatre]{Couleur};boolean Libre,Multiplication,Texte;Libre:=\useKV[ClesPQuatre]{Libre};Multiplication=\useKV[ClesPQuatre]{Multiplication};Texte:=\useKV[ClesPQuatre]{Texte};if Texte:string Consignes;Consignes=\useKV[ClesPQuatre]{Consignes};fi;}]
    % On calcule le nombre de cases
    nchauteur:=0;
    for p_=#1:
    nchauteur:=incr nchauteur;
    endfor;
    nclargeur:=0;
    for p_=#2:
    nclargeur:=incr nclargeur;
    endfor;
    if Libre=false:
    nchauteur:=7;
    nclargeur:=7;
    fi;
    %On affiche
    pair A,B,C,D,H[],V[],M[][];
    A=(0,0);
    B-A=Largeur*(nclargeur,0);
    C-B=Largeur*(0,nchauteur);
    D-C=A-B;
    fill polygone(A,B,C,D) withcolor fond;
    trace polygone(A,B,C,D);
    for k=0 upto (nclargeur-1):
    for l=0 upto (nchauteur-1):
    M[k][l]=A+0.5*(Largeur,Largeur)+k*(Largeur,0)+l*(0,Largeur);
    fill cercles(M[k][l],0.4*Largeur) withcolor blanc;
    trace cercles(M[k][l],0.4*Largeur);
    endfor;
    endfor;
    labeloffset:=labeloffset*2;
    if Libre:
    if Texte:
    label.llft(LATEX("\begin{minipage}{"&decimal(LargeurUn)&"pt}"&Consignes&"\end{minipage}") scaled Echelle,A);
    fi;
    else:
    if Multiplication:
    label.llft(btex $\times$ etex scaled Echelle,A);
    else:
    label.llft(btex $+$ etex scaled Echelle,A);
    fi;
    fi;
    labeloffset:=labeloffset/2;
    vardef Vertical(text t)=
    n:=0;
    for p_=t:
    label.lft(LATEX(p_) scaled Echelle,A+(0,n*Largeur+Largeur/2));
    n:=n+1;
    endfor;
    enddef;
    vardef Horizontal(text t)=
    n:=0;
    for p_=t:
    label.bot(LATEX(p_) scaled Echelle,A+(n*Largeur+Largeur/2,0));
    n:=n+1;
    endfor;
    enddef;
    labeloffset:=labeloffset*4;
    Vertical(#1);
    Horizontal(#2);
  \end{mpost}
  \fi%
}%