%%%
% Fraction Nombre
%%%
\def\filedateFractionNombre{2025/05/28}%
\def\fileversionFractionNombre{0.1a}%
\message{-- \filedateFractionNombre\space v\fileversionFractionNombre}%
%
\newtoks\tokFractionNombrePerso%
\def\UpdatetoksFN#1\nil{\addtotok\tokFractionNombrePerso{"#1",}}%

\setKVdefault[ClesFN]{Unite=5cm,Aire=false,Solution=false,Quadrillage=false,PasQuad=5mm,HautQuad=3,LargQuad=8,Vide=false,Couleur=blue,UniteAire=1x1,Pointilles=false,Tentatives=10,SansLegende=false,CouleurAire=LightSteelBlue,CouleurUniteAire=0.7white,Perso={}}%

\NewDocumentCommand\FractionNombre{om}{%
  \useKVdefault[ClesFN]%
  \setKV[ClesFN]{#1}%
  \tokFractionNombrePerso{}%
  \ifemptyKV[ClesFN]{Perso}{}{%
    \xdef\PfCFooCheminFN{\useKV[ClesFN]{Perso}}%
    \setsepchar{,}\ignoreemptyitems%
    \readlist*\PfCListeDeplacements{\PfCFooCheminFN}%
    \reademptyitems%
    \foreachitem\compteur\in\PfCListeDeplacements{\expandafter\UpdatetoksFN\compteur\nil}%
  }%
  \StrCut{#2}{/}\PfCNumA\PfCNumB%
  \ifboolKV[ClesFN]{Aire}{%
    \StrCut{\useKV[ClesFN]{UniteAire}}{x}\PfCAirex\PfCAirey%
    \ifemptyKV[ClesFN]{Perso}{%
      \BuildFractionNombreAire{\PfCNumA}{\PfCNumB}{\PfCAirex}{\PfCAirey}%
    }{%
      \BuildFractionNombreAirePerso{\PfCNumA}{\PfCNumB}{\PfCAirex}{\PfCAirey}{\the\tokFractionNombrePerso}%
    }%
  }{%
    \ifboolKV[ClesFN]{Quadrillage}{%
      \BuildFractionNombreQuadrillage{\PfCNumA}{\PfCNumB}{\the\tokFractionNombrePerso}%
    }{%
      \BuildFractionNombreSegment{\PfCNumA}{\PfCNumB}%
    }%
  }%
}%

\NewDocumentCommand\BuildFractionNombreAirePerso{mmmmm}{%
  \mplibforcehmode%
  \begin{mplibcode}
    vardef LireMotif(text t)=
      lmotif=0;
      hmotif=0;
      for p_=t:
        hmotif:=hmotif+1;
        if lmotif<(length p_):
          lmotif:=length p_;
        fi;
      endfor;
    enddef;
    % 
    vardef PlacerMotif(text t)=
      ChoixLigneD=hmotif+ceiling(uniformdeviate(HautQuad-1-hmotif));
      ChoixColonneD=ceiling(uniformdeviate(LargQuad-#3-1-lmotif));
      Colonne:=ChoixColonneD;
      Ligne=ChoixLigneD;
      for p_=t:
        Colonne:=ChoixColonneD;
        for k=0 upto ((length p_)-1):
          if (substring(k,k+1) of p_)="x":
            fill ((unitsquare scaled 5mm) shifted (5mm*(Colonne-1,Ligne-1))) withcolor CouleurAire;
          fi;
          Colonne:=Colonne+1;
        endfor;
        Ligne:=Ligne-1;
      endfor;
    enddef;
    % 
    color CouleurAire,CouleurUniteAire;
    CouleurAire=\useKV[ClesFN]{CouleurAire};
    CouleurUniteAire=\useKV[ClesFN]{CouleurUniteAire};
    PasQuad=\useKV[ClesFN]{PasQuad};
    HautQuad=\useKV[ClesFN]{HautQuad};
    LargQuad=\useKV[ClesFN]{LargQuad};
    pair A,B,C,D,U[];
    A=(0,0);
    B-A=PasQuad*(LargQuad,0);
    C-B=PasQuad*(0,HautQuad);
    D-C=A-B;
    % l'unité
    U0=C;
    U1-U0=#3*PasQuad*(-1,0);
    U3-U0=#4*PasQuad*(0,-1);
    U2-U3=U1-U0;
    % 
    LireMotif(#5);
    PlacerMotif(#5);
    % Tracage
    fill polygone(U0,U1,U2,U3) withcolor CouleurUniteAire;
    label.top(TEX("\textbf{1 ua}"),iso(U1,U0));
    % Le quadrillage
    trace polygone(A,B,C,D);
    for k=1 upto LargQuad-1:
      trace (k/LargQuad)[A,B]--(k/LargQuad)[D,C];
    endfor;
    for k=1 upto HautQuad-1:
      trace (k/HautQuad)[A,D]--(k/HautQuad)[B,C];
    endfor;
  \end{mplibcode}%
}%

\NewDocumentCommand\BuildFractionNombreAire{mmmm}{%
  \mplibforcehmode%
  \begin{mplibcode}
    boolean Impossible[][];
    % 
    vardef InitialisationZone=
      for k=-1 upto HautQuad+1:
        for l=-1 upto LargQuad+1:
          Impossible[k][l]=true;
        endfor;
      endfor;
      for k=1 upto HautQuad-1:
        for l=1 upto LargQuad-#3-1:
          Impossible[k][l]:=false;
        endfor;
      endfor;
    enddef;
    % 
    vardef RAZZone=
      pair PileChemin[];
      indiceChemin:=0;
    enddef;
    %
    def PushChemin(expr tt)=
      if indiceChemin<1:
        PileChemin[1]:=tt;
        indiceChemin:=1;
      else:
        PileChemin[indiceChemin+1]:=tt;
        indiceChemin:=indiceChemin+1;
      fi;
    enddef;
    % 
    def PopChemin=
      tentative:=tentative+1;
      currentpicture:=nullpicture;
      RAZZone;
      for k=-1 upto HautQuad:
        for l=-1 upto LargQuad:
          Impossible[k][l]:=true;
        endfor;
      endfor;
      for k=1 upto HautQuad-1:
        for l=1 upto LargQuad-#3-1:
          Impossible[k][l]:=false;
        endfor;
      endfor;
      %Redemarrage
      nbcaseschoisies:=1;
      PushChemin((ChoixLigneD,ChoixColonneD));
      fill ((unitsquare scaled 5mm) shifted (5mm*(ChoixColonneD-1,ChoixLigneD-1))) withcolor CouleurAire;
      Impossible[ChoixLigneD][ChoixColonneD]:=true;
      VoisinDispo(ChoixLigneD,ChoixColonneD);
    enddef;
    % 
    % Pile des cases voisines de la case parcourue
    pair PileVoisin[];
    numeric indiceVoisin;
    indiceVoisin=0;
    % 
    vardef RAZPileVoisin=
      indiceVoisin:=0;
    enddef;
    % 
    def PushVoisin(expr tt)=
      if indiceVoisin<1:
        PileVoisin[1]:=tt;
        indiceVoisin:=1;
      else:
        PileVoisin[indiceVoisin+1]:=tt;
        indiceVoisin:=indiceVoisin+1;
      fi;
    enddef;
    % 
    vardef VoisinDispo(expr la,lo)=
      RAZPileVoisin;
      numeric nbvoisin;
      nbvoisin=0;
      if Impossible[la+1][lo]=false:
        nbvoisin:=nbvoisin+1;
        PushVoisin((la+1,lo));
      fi;
      if Impossible[la-1][lo]=false:
        nbvoisin:=nbvoisin+1;
        PushVoisin((la-1,lo));
      fi;
      if Impossible[la][lo+1]=false:
        nbvoisin:=nbvoisin+1;
        PushVoisin((la,lo+1));
      fi;
      if Impossible[la][lo-1]=false:
        nbvoisin:=nbvoisin+1;
        PushVoisin((la,lo-1));
      fi;
    enddef;
    % 
    color CouleurAire,CouleurUniteAire;
    CouleurAire=\useKV[ClesFN]{CouleurAire};
    CouleurUniteAire=\useKV[ClesFN]{CouleurUniteAire};
    % 
    boolean Vide,SansLegende;
    Vide=\useKV[ClesFN]{Vide};
    SansLegende=\useKV[ClesFN]{SansLegende};
    PasQuad=\useKV[ClesFN]{PasQuad};
    HautQuad=\useKV[ClesFN]{HautQuad};
    LargQuad=\useKV[ClesFN]{LargQuad};
    Tentatives=\useKV[ClesFN]{Tentatives};
    pair A,B,C,D,U[];
    A=(0,0);
    B-A=PasQuad*(LargQuad,0);
    C-B=PasQuad*(0,HautQuad);
    D-C=A-B;
    % l'unité
    U0=C;
    U1-U0=#3*PasQuad*(-1,0);
    U3-U0=#4*PasQuad*(0,-1);
    U2-U3=U1-U0;
    % Le nombres total de cases à colorier
    NbTotalCasesAColorier=((#1*#3*#4)/#2);
    NbTotalCasesRestantes=HautQuad*(LargQuad-#3-1);
    % 
    InitialisationZone;
    RAZZone;
    % 
    ChoixLigneD=ceiling(uniformdeviate(HautQuad-1));
    ChoixColonneD=ceiling(uniformdeviate(LargQuad-#3-1));
    % 
    tentative:=1;
    if Vide=false:
      PushChemin((ChoixLigneD,ChoixColonneD));
      nbcaseschoisies=1;
      fill ((unitsquare scaled 5mm) shifted (5mm*(ChoixColonneD-1,ChoixLigneD-1))) withcolor CouleurAire;
      Impossible[ChoixLigneD][ChoixColonneD]:=true;
      VoisinDispo(ChoixLigneD,ChoixColonneD);
      % Le "parcours"
      forever: exitif (nbcaseschoisies>NbTotalCasesAColorier-1) or (tentative>Tentatives);
        nb:=ceiling(uniformdeviate(nbvoisin));
        if nb>0:
          for k=1 upto nbvoisin:
            Impossible[xpart(PileVoisin[nb])][ypart(PileVoisin[nb])]:=true;
          endfor;
          PushChemin((xpart(PileVoisin[nb]),ypart(PileVoisin[nb])));
          nbcaseschoisies:=nbcaseschoisies+1;
          fill ((unitsquare scaled 5mm) shifted (5mm*(ypart(PileVoisin[nb])-1,xpart(PileVoisin[nb])-1))) withcolor CouleurAire;
          VoisinDispo(xpart(PileChemin[indiceChemin]),ypart(PileChemin[indiceChemin]));
        else:
          PopChemin;
        fi;
      endfor;
    fi;
    % Tracage
    if tentative>Tentatives:
      currentpicture:=nullpicture;
      picture MiseEnGarde;
      MiseEnGarde=image(
      label(TEX("\begin{minipage}{0.5\linewidth}
        La construction automatique a échouée. Relancez en augmentant le nombre de tentatives ou en augmentant les dimensions du quadrillage (Hauteur,Largeur)
      \end{minipage}"),(0,0));
      );
      draw (((llcorner MiseEnGarde)--(lrcorner MiseEnGarde)--(urcorner MiseEnGarde)--(ulcorner MiseEnGarde)--cycle) scaled 1.1) withpen pensquare scaled 2;
      draw MiseEnGarde;
    else:
      if SansLegende=false:
        fill polygone(U0,U1,U2,U3) withcolor CouleurUniteAire;
        label.top(TEX("\textbf{1 ua}"),iso(U1,U0));
      fi;
      %Le quadrillage
      trace polygone(A,B,C,D);
      for k=1 upto LargQuad-1:
        trace (k/LargQuad)[A,B]--(k/LargQuad)[D,C];
      endfor;
      for k=1 upto HautQuad-1:
        trace (k/HautQuad)[A,D]--(k/HautQuad)[B,C];
      endfor;
    fi;
  \end{mplibcode}%
}%

\NewDocumentCommand\BuildFractionNombreSegment{mm}{%
  \mplibforcehmode%
  \begin{mplibcode}
    Unite:=\useKV[ClesFN]{Unite};
    boolean Solution,Vide;
    Solution=\useKV[ClesFN]{Solution};
    Vide=\useKV[ClesFN]{Vide};
    color CoulFN;
    CoulFN=\useKV[ClesFN]{Couleur};
    Num:=#1;
    Pas:=#2;
    pair A,B,C,D;
    A=(0,0);
    B=Unite*(1,0);
    if Num>Pas:
      C=((Num+1)/Pas)[A,B];
      Total=Num+1;
    else:
      C=B;
      Total=Pas;
    fi;
    D=(Num/Pas)[A,B];      
    trace segment(A,C);
    for k=0 upto Total:
      trace ((0,-1mm)--(0,1mm)) shifted ((k/Pas)[A,B]);
    endfor;
    trace cotationmil(A,B,5mm,15,TEX("1 ul"));
    if Solution:
      draw (A--D) withpen pencircle scaled 2 withcolor CoulFN;
      trace cotationmil(A,D,-5mm,25,TEX("$?=\dfrac{"&decimal(#1)&"}{"&decimal(#2)&"}$~ul"));
    else:
      if Vide:
      else:
        trace cotationmil(A,D,-5mm,25,TEX("$?=\dots$~ul"));
      fi;
    fi;
  \end{mplibcode}%
}%

\NewDocumentCommand\BuildFractionNombreQuadrillage{mmm}{%
  \mplibforcehmode%
  \begin{mplibcode}
    Unite:=#2;%\useKV[ClesFN]{Unite};%en carreaux
    HautQuad:=\useKV[ClesFN]{HautQuad};
    Largeur:=Unite;%en carreaux
    boolean Solution,Vide,Creation,Pointilles;
    Solution=\useKV[ClesFN]{Solution};
    Vide=\useKV[ClesFN]{Vide};
    \ifemptyKV[ClesFN]{Perso}{Creation=false;}{Creation=true;}
    Pointilles=\useKV[ClesFN]{Pointilles};
    color CoulFN;
    CoulFN=\useKV[ClesFN]{Couleur};
    Num:=#1;
    Pas:=#2;
    PasQuad:=\useKV[ClesFN]{PasQuad};
    pair A,B,C,D;
    A=(0,0);
    B=(((#1 div #2)+1)*Unite+1)*PasQuad*(1,0);
    C-B=(0,HautQuad*PasQuad);
    D-C=A-B;
    trace polygone(A,B,C,D);
    TotalLargeur=(((#1 div #2)+1)*Unite+1);
    for k=1 upto TotalLargeur-1:
      trace (k/TotalLargeur)[A,B]--(k/TotalLargeur)[D,C];
    endfor;
    for k=1 upto HautQuad-1:
      trace (k/HautQuad)[A,D]--(k/HautQuad)[B,C];
    endfor;
    % Macro pour le chemin perso
    vardef RemplirChemin(text t)=
      nbpoints:=0;
      % On compte le dénivelé
      denivele=0;
      denivmax:=0;
      denivmin:=0;
      for p_=t:
        if p_="+":
          denivmax:=denivmax+1;
        elseif p_="-":
          denivmin:=denivmin-1;
        fi;
      endfor;
      depart:=-(denivmin)+floor(uniformdeviate(HautQuad-2-abs(denivmax-abs(denivmin))));
      ch[0]=PasQuad*(0,depart);
      for p_=t:
        nbpoints:=nbpoints+1;
        if p_=">":
          ch[nbpoints]=ch[nbpoints-1]+PasQuad*(1,0);
        elseif p_="<":
          ch[nbpoints]=ch[nbpoints-1]+PasQuad*(-1,0);
        elseif p_="+":
          ch[nbpoints]=ch[nbpoints-1]+PasQuad*(0,1);
        elseif p_="-":
          ch[nbpoints]=ch[nbpoints-1]+PasQuad*(0,-1);
        fi;
      endfor;
    enddef;
    % On choisit le départ.
    pair ch[];
    numeric xe[],ye[];
    if Creation:
      RemplirChemin(#3);
    else:
      depart:=floor(uniformdeviate(HautQuad-1));
      ch[0]=PasQuad*(0,depart);
      xe0=0;
      ye0=depart;
      for k=1 upto #1:
        if (k mod 2)=1:
          ch[k]-ch[k-1]=PasQuad*(1,0);
          xe[k]=xe[k-1]+1;
          ye[k]=ye[k-1];
        else:
          if ye[k-1]=0:
            alea:=uniformdeviate(2);
            if alea<1:
              ch[k]-ch[k-1]=PasQuad*(0,1);
              xe[k]=xe[k-1];
              ye[k]=ye[k-1]+1;
            else:
              ch[k]-ch[k-1]=PasQuad*(1,0);
              xe[k]=xe[k-1]+1;
              ye[k]=ye[k-1];
            fi;
          elseif ye[k-1]=2:
            alea:=uniformdeviate(2);
            if alea<1:
              ch[k]-ch[k-1]=PasQuad*(0,-1);
              xe[k]=xe[k-1];
              ye[k]=ye[k-1]-1;
            else:
              ch[k]-ch[k-1]=PasQuad*(1,0);
              xe[k]=xe[k-1]+1;
              ye[k]=ye[k-1];
            fi;
          else:
            alea:=uniformdeviate(3);
            if alea<1:
              ch[k]-ch[k-1]=PasQuad*(0,1);
              xe[k]=xe[k-1];
              ye[k]=ye[k-1]+1;
            elseif alea<2:
              ch[k]-ch[k-1]=PasQuad*(1,0);
              xe[k]=xe[k-1]+1;
              ye[k]=ye[k-1];
            else:
              ch[k]-ch[k-1]=PasQuad*(0,-1);
              xe[k]=xe[k-1];
              ye[k]=ye[k-1]-1;
            fi;
          fi;      
        fi;
      endfor;
    fi;
    if Vide=false:
      trace ch[0] for k=1 upto #1:--ch[k] endfor withpen pencircle scaled 2 if Pointilles: dashed evenly else: withcolor CoulFN fi;
    fi;
    trace cotationmil(D,(D+#2*(PasQuad,0)),5mm,15,TEX("1 ul"));
    trace segment(D,D+#2*(PasQuad,0)) withpen pencircle scaled 1.5;
  \end{mplibcode}%
}%
