π
<-
Chat plein-écran
[^]

Mise à jour matplotlib Casio Graph 90/35+E II : arrow()

Online

Mise à jour matplotlib Casio Graph 90/35+E II : arrow()

Unread postby critor » 18 Aug 2020, 10:30

Pour cette rentrée 2020, la formidable application
Python
des
Casio Graph 90+E
et
Graph 35+E II
si correctement mise à jour
(ce qu'il est notamment conseillé de faire si tu viens d'acheter la calculatrice)
t'offre 3 modules importables pour tes scripts :
  • math
    pour les fonctions mathématiques, un standard
  • random
    pour l'aléatoire, un standard
  • et
    casioplot
    , un module graphique propriétaire permettant à tes scripts d'allumer des pixels de l'écran dans la couleur de ton choix

De plus,
Casio
diffuse 2 scripts
Python
à rajouter manuellement dans ta calculatrice et qui s'appuient sur le module
casioplot
précédent :
  • turtle.py
    , un script fantastique de plus de 300 lignes qui reproduit sur ta calculatrice le fonctionnement du module
    turtle
    standard
  • matplotl.py
    , un script monumental de plus de 600 lignes qui s'occupe quant à lui de reproduire sur ta calculatrice le fonctionnement du module standard
    matplotlib.pyplot
Il s'agit donc de réimplémentations en
Python
des modules standard
turtle
et
matplotlib.pyplot
, un travail à la fois colossal et d'excellente facture, car hautement fidèle aux modules standard en question ! :bj:

Tous les liens de téléchargement seront disponibles en fin d'article.


12775Cela n'enlève rien à leurs énormes qualités supérieures par rapport à ce qui est disponible sur certaines
Pythonnettes
concurrentes, mais une réécriture intégrale ne peut pas être parfaite du premier coup.

Nous nous intéresserons ici au script
matplotl.py
, et plus précisément à sa fonction de tracé de flèche/vecteur notamment pour l'enseignement de
Physique-Chimie
en
Seconde
,
arrow()
.
Absolument pas pour se moquer de
Casio
, mais simplement parce que c'est intéressant et hautement formateur.

Voici un petit script avec de quoi te tracer un soleil de vecteurs
(ou un champ de vecteurs radial pour ceux qui préfèrent)
:
Code: Select all
try:
  from matplotlib.pyplot import *
except ImportError:
  from matplotl import *
from math import cos, sin, pi

def radians(x):
  return x * pi / 180

def autoround(x):
  xr = round(x, 0)
  if abs(x - xr) < 10 ** -15:
    x = xr
  return x

def rotarrow(x0, y0, rx, ry, t1, t2, ts, hw, hl, ec, fc):
  for k in range(t1, t2 + ts, ts):
    kr = radians(k)
    w, h = autoround(rx * cos(kr)), autoround(ry * sin(kr))
    arrow(x0, y0, w, h, head_width=hw, head_length=hl, ec=ec, fc=fc)

Graph 35+E II
Graph 90+E
NumWorks
ordi
Code: Select all
rotarrow(.0625, .0625, .75, .75, 0, 90, 10, .075, .1875, 'r', 'b')
show()

Bon la
NumWorks
semble ignorer les paramètres de couleur pour faire absolument n'importe quoi, mais ce n'est pas ce qui nous intéresse aujourd'hui. Voyons donc plutôt les défauts chez
Casio
.

Sur
Graph 35+E II
tout semble bon. Par contre sur
Graph 90+E
il y a un problème avec la couleur des pointes, dans le cas particulier où elles sont orientées horizontalement ou verticalement.

Effectivement ça ne va pas, tentons de comprendre et corriger directement le fichier de
Casio
puisque ce dernier a eu la gentillesse de laisser le code source consultable et modifiable contrairement à d'autres. ;)

La variable
color
est donc la couleur utilisée pour le tracé du segment via un appel
plot()
commun à toutes les orientations.
La variable
headcolor
est quant à elle la couleur souhaitée pour la pointe.
Pour le tracé de la pointe il y a 2 cas particuliers pour les directions horizontales et verticales, et effectivement les appels
plot()
associés sont faux, réutilisant
color
comme paramètre de couleur. La correction est triviale, lignes n°23 et 29 dans les extraits de code ci-dessous : :)
maptplotl.py

de
Casio
matplotl.py

corrigé
Code: Select all
def arrow(x,y,dx,dy,**kwargs):
    global win_scaling
    a=x+dx
    b=y+dy
    win_scaling='fixed'
    color=kwargs.get('ec','k')
    color=kwargs.get('edgecolor',color)
    headcolor=kwargs.get('fc',color)
    headcolor=kwargs.get('facecolor',headcolor)
    L=kwargs.get('head_width',0.003)
    l=kwargs.get('head_length',1.5*L)
    plot((x,a),(y,b),color)

    def resol(A,B,C):
        D=B**2-4*A*C
        if D>0:
            return((-B-D**0.5)/(2*A),(-B+D**0.5)/(2*A))
    if dx==0:
        if dy>=0:
            c=1
        else:
            c=-1
        plot((a-L/2,a+L/2,a,a-L/2),(b,b,b+c*l,b),color)
    elif dy==0:
        if dx>=0:
            c=1
        else:
            c=-1
        plot((a,a,a+c*l,a),(b-L/2,b+L/2,b,b-L/2),color)
Code: Select all
def arrow(x,y,dx,dy,**kwargs):
    global win_scaling
    a=x+dx
    b=y+dy
    win_scaling='fixed'
    color=kwargs.get('ec','k')
    color=kwargs.get('edgecolor',color)
    headcolor=kwargs.get('fc',color)
    headcolor=kwargs.get('facecolor',headcolor)
    L=kwargs.get('head_width',0.003)
    l=kwargs.get('head_length',1.5*L)
    plot((x,a),(y,b),color)

    def resol(A,B,C):
        D=B**2-4*A*C
        if D>0:
            return((-B-D**0.5)/(2*A),(-B+D**0.5)/(2*A))
    if dx==0:
        if dy>=0:
            c=1
        else:
            c=-1
        plot((a-L/2,a+L/2,a,a-L/2),(b,b,b+c*l,b),headcolor)
    elif dy==0:
        if dx>=0:
            c=1
        else:
            c=-1
        plot((a,a,a+c*l,a),(b-L/2,b+L/2,b,b-L/2),headcolor)


Bon mais ça c'était un détail. Voici maintenant beaucoup plus dérangeant et épicé : ;)
Graph 35+E II
Graph 90+E
NumWorks
ordi
Code: Select all
rotarrow(.475, .5, .45, .4, 0, 360, 10, .05, .1, 'r', 'b')
axis([0, 1, 0, 1])
show()

Mais sur
Graph 35+E II
et
Graph 90+E
ça ne va pas du tout... Mais qu'est-ce que c'est que cette horreur de soleil à moitié fané ?... :#roll#:

Dans certains cas, les pointes de flèches/vecteurs sont visiblement tracées à l'envers. Là pour le coup c'est un
bug
bien plus profond et non une simple étourderie.

Tentons de comprendre un peu mieux quand est-ce que cela se produit :
Graph 35+E II
Graph 90+E
NumWorks
ordi
Code: Select all
for k in range(4):
  rotarrow(.475 - (k <= 1), .5 - (k % 2), .45, .4, 0, 360, 15, .075, .1, 'r', 'b')
axis([-1, 1, -1, 1])
show()

Il semble que les pointes de flèches soient ainsi montées à l'envers lorsqu'elles ont une abscisse négative
(x<0)
. Il s'agirait donc a priori d'une erreur de signe, faut-il encore trouver où changer le signe dans le code.

Notons que le problème concerne des flèches qui ne sont ni horizontales ni verticales, et l'erreur est donc à chercher cette fois-ci dans le bloc traitant le cas général. Or il y a justement un test de signe dans ce cas, ligne 34 ci-dessous. Changeons cela... ;)
maptplotl.py

de
Casio
matplotl.py

corrigé






Code: Select all
def arrow(x,y,dx,dy,**kwargs):
    global win_scaling
    a=x+dx
    b=y+dy
    win_scaling='fixed'
    color=kwargs.get('ec','k')
    color=kwargs.get('edgecolor',color)
    headcolor=kwargs.get('fc',color)
    headcolor=kwargs.get('facecolor',headcolor)
    L=kwargs.get('head_width',0.003)
    l=kwargs.get('head_length',1.5*L)
    plot((x,a),(y,b),color)

    def resol(A,B,C):
        D=B**2-4*A*C
        if D>0:
            return((-B-D**0.5)/(2*A),(-B+D**0.5)/(2*A))
    if dx==0:
        if dy>=0:
            c=1
        else:
            c=-1
        plot((a-L/2,a+L/2,a,a-L/2),(b,b,b+c*l,b),headcolor)
    elif dy==0:
        if dx>=0:
            c=1
        else:
            c=-1
        plot((a,a,a+c*l,a),(b-L/2,b+L/2,b,b-L/2),headcolor)
    else:
        m=dy/dx
        p=y-m*x
        S=resol(m**2+1,2*(-a-b*m+m*p),p**2+a**2+b**2-l**2-2*b*p)
        if S[0]*dx<0:
            X=S[0]
        else:
            X=S[1]
        Y=m*X+p
        k=b+a/m
        T=resol(1+1/m**2,2*(-a-k/m+b/m),a**2+k**2-2*b*k+b**2-(L**2)/4)
        plot((T[0],T[1],X,T[0]),(-T[0]/m+k,-T[1]/m+k,Y,-T[0]/m+k),headcolor)
Code: Select all
def arrow(x,y,dx,dy,**kwargs):
    global win_scaling
    a=x+dx
    b=y+dy
    win_scaling='fixed'
    color=kwargs.get('ec','k')
    color=kwargs.get('edgecolor',color)
    headcolor=kwargs.get('fc',color)
    headcolor=kwargs.get('facecolor',headcolor)
    L=kwargs.get('head_width',0.003)
    l=kwargs.get('head_length',1.5*L)
    plot((x,a),(y,b),color)

    def resol(A,B,C):
        D=B**2-4*A*C
        if D>0:
            return((-B-D**0.5)/(2*A),(-B+D**0.5)/(2*A))
    if dx==0:
        if dy>=0:
            c=1
        else:
            c=-1
        plot((a-L/2,a+L/2,a,a-L/2),(b,b,b+c*l,b),headcolor)
    elif dy==0:
        if dx>=0:
            c=1
        else:
            c=-1
        plot((a,a,a+c*l,a),(b-L/2,b+L/2,b,b-L/2),headcolor)
    else:
        m=dy/dx
        p=y-m*x
        S=resol(m**2+1,2*(-a-b*m+m*p),p**2+a**2+b**2-l**2-2*b*p)
        if S[0]*dx*x<0:
            X=S[0]
        else:
            X=S[1]
        Y=m*X+p
        k=b+a/m
        T=resol(1+1/m**2,2*(-a-k/m+b/m),a**2+k**2-2*b*k+b**2-(L**2)/4)
        plot((T[0],T[1],X,T[0]),(-T[0]/m+k,-T[1]/m+k,Y,-T[0]/m+k),headcolor)

Ah ben non, ce n'est pas encore ça... cela corrige bien les pointes enfichées sur une extrémité de segment d'abscisse négative, mais pas celles qui franchissent l'axe des ordonnées donnant donc une pointe d'abscisse négative bien que montée sur une extrémité d'abscisse positive.

Les deux sens de montage de la flèche pour l'orientation du segment sont en fait retournées en abscisses par un appel
resol()
, simple fonction donnant les racines d'un polynôme du second degré.

Reste donc à choisir le bon sens de montage, et le test officiel S[0]*dx<0 ainsi que notre test S[0]*dx*x<0 semblent donc tous les deux faux.

En fait nous ne voyons même pas en quoi la réponse dépendrait du signe de la racine S[0]... à la rigueur de l'ordre de S[0] et S[1] pour savoir qui est à gauche et qui est à droite, mais pas du signe... et ici il n'y a même pas à se préoccuper de l'ordre puisque 1+1/m**2, premier paramètre de l'appel
resol()
, est strictement positif.

Faire pointer à gauche ou à droite, non ici cela ne dépend plus que d'une seule et unique chose, le signe de
dx
, et le bon test corrigé en ligne 34 ci-dessous est donc dx<0.
On peut bien se permettre une petite coquille après s'être tapé plus de 320 lignes. ;)

maptplotl.py

de
Casio
matplotl.py

corrigé






Code: Select all
def arrow(x,y,dx,dy,**kwargs):
    global win_scaling
    a=x+dx
    b=y+dy
    win_scaling='fixed'
    color=kwargs.get('ec','k')
    color=kwargs.get('edgecolor',color)
    headcolor=kwargs.get('fc',color)
    headcolor=kwargs.get('facecolor',headcolor)
    L=kwargs.get('head_width',0.003)
    l=kwargs.get('head_length',1.5*L)
    plot((x,a),(y,b),color)

    def resol(A,B,C):
        D=B**2-4*A*C
        if D>0:
            return((-B-D**0.5)/(2*A),(-B+D**0.5)/(2*A))
    if dx==0:
        if dy>=0:
            c=1
        else:
            c=-1
        plot((a-L/2,a+L/2,a,a-L/2),(b,b,b+c*l,b),headcolor)
    elif dy==0:
        if dx>=0:
            c=1
        else:
            c=-1
        plot((a,a,a+c*l,a),(b-L/2,b+L/2,b,b-L/2),headcolor)
    else:
        m=dy/dx
        p=y-m*x
        S=resol(m**2+1,2*(-a-b*m+m*p),p**2+a**2+b**2-l**2-2*b*p)
        if S[0]*dx<0:
            X=S[0]
        else:
            X=S[1]
        Y=m*X+p
        k=b+a/m
        T=resol(1+1/m**2,2*(-a-k/m+b/m),a**2+k**2-2*b*k+b**2-(L**2)/4)
        plot((T[0],T[1],X,T[0]),(-T[0]/m+k,-T[1]/m+k,Y,-T[0]/m+k),headcolor)
Code: Select all
def arrow(x,y,dx,dy,**kwargs):
    global win_scaling
    a=x+dx
    b=y+dy
    win_scaling='fixed'
    color=kwargs.get('ec','k')
    color=kwargs.get('edgecolor',color)
    headcolor=kwargs.get('fc',color)
    headcolor=kwargs.get('facecolor',headcolor)
    L=kwargs.get('head_width',0.003)
    l=kwargs.get('head_length',1.5*L)
    plot((x,a),(y,b),color)

    def resol(A,B,C):
        D=B**2-4*A*C
        if D>0:
            return((-B-D**0.5)/(2*A),(-B+D**0.5)/(2*A))
    if dx==0:
        if dy>=0:
            c=1
        else:
            c=-1
        plot((a-L/2,a+L/2,a,a-L/2),(b,b,b+c*l,b),headcolor)
    elif dy==0:
        if dx>=0:
            c=1
        else:
            c=-1
        plot((a,a,a+c*l,a),(b-L/2,b+L/2,b,b-L/2),headcolor)
    else:
        m=dy/dx
        p=y-m*x
        S=resol(m**2+1,2*(-a-b*m+m*p),p**2+a**2+b**2-l**2-2*b*p)
        if dx<0:
            X=S[0]
        else:
            X=S[1]
        Y=m*X+p
        k=b+a/m
        T=resol(1+1/m**2,2*(-a-k/m+b/m),a**2+k**2-2*b*k+b**2-(L**2)/4)
        plot((T[0],T[1],X,T[0]),(-T[0]/m+k,-T[1]/m+k,Y,-T[0]/m+k),headcolor)

En attendant une mise à jour officielle qui réglera cela et peut-être d'autres choses, c'est donc cette version corrigée que nous distribuerons.


Téléchargements
:

Image
User avatar
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Level up: 9.2%
 
Posts: 36077
Images: 9867
Joined: 25 Oct 2008, 00:00
Location: Montpellier
Gender: Male
Calculator(s):
Class: Lycée
YouTube: critor3000
Twitter: critor2000
Facebook: critor.ti
GitHub: critor

Re: Mise à jour matplotlib Casio Graph 90/35+E II : arrow()

Unread postby Dogm » 18 Aug 2020, 11:31

Jolie test. :)

critor wrote:Bon la NumWorks semble ignorer les paramètres de couleur pour faire absolument n'importe quoi, mais ce n'est pas ce qui nous intéresse aujourd'hui. Voyons donc plutôt les défauts chez Casio.


La Graph 35+E II aussi, elle affiche tout en noir et blanc. :troll:
User avatar
DogmEcrivain
Niveau 12: CP (Calculatrice sur Pattes)
Niveau 12: CP (Calculatrice sur Pattes)
Level up: 10.7%
 
Posts: 113
Images: 7
Joined: 14 Nov 2019, 18:53
Location: Lyon, France
Gender: Male
Calculator(s):
Class: Lycéen 1ère Math, SI & NSI
GitHub: tim_ats_d

Online

Re: Mise à jour matplotlib Casio Graph 90/35+E II : arrow()

Unread postby critor » 18 Aug 2020, 11:36

Merci. :)

Dogm wrote:
critor wrote:Bon la NumWorks semble ignorer les paramètres de couleur pour faire absolument n'importe quoi, mais ce n'est pas ce qui nous intéresse aujourd'hui. Voyons donc plutôt les défauts chez Casio.


La Graph 35+E II aussi, elle affiche tout en noir et blanc. :troll:


Oui mais elle n'a pas le choix, pas de possibilité de faire mieux, donc à la différence on lui pardonne. :p
Image
User avatar
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Level up: 9.2%
 
Posts: 36077
Images: 9867
Joined: 25 Oct 2008, 00:00
Location: Montpellier
Gender: Male
Calculator(s):
Class: Lycée
YouTube: critor3000
Twitter: critor2000
Facebook: critor.ti
GitHub: critor

Online

Re: Mise à jour matplotlib Casio Graph 90/35+E II : arrow()

Unread postby cent20 » 18 Aug 2020, 11:47

Dogm wrote:Jolie test. :)

critor wrote:Bon la NumWorks semble ignorer les paramètres de couleur pour faire absolument n'importe quoi, mais ce n'est pas ce qui nous intéresse aujourd'hui. Voyons donc plutôt les défauts chez Casio.


La Graph 35+E II aussi, elle affiche tout en noir et blanc. :troll:


Moi je trouve les couleurs de NumWorks bien choisie. Sobres, douces, délicates ! Ma fille adore !
Je suis d'accord que la Graph 35+E II a un énorme problème de respect des couleurs, c'est bien dommage !
Image
Enseignant de mathématiques et de spécialité NSI ( projets, tutos ...)
:favorite: NumWork, Python : démineur, snake, tétris
User avatar
cent20Premium
Niveau 13: CU (Calculateur Universel)
Niveau 13: CU (Calculateur Universel)
Level up: 25.2%
 
Posts: 499
Images: 38
Joined: 17 May 2012, 09:49
Location: Avignon
Gender: Male
Calculator(s):
Twitter: nsi_xyz

Re: Mise à jour matplotlib Casio Graph 90/35+E II : arrow()

Unread postby Afyu » 18 Aug 2020, 13:54

critor wrote:Bon la
NumWorks
semble ignorer les paramètres de couleur pour faire absolument n'importe quoi, mais ce n'est pas ce qui nous intéresse aujourd'hui.


C'est parce que la
NumWorks
c'est une rebelle :p

Il me semble que ce n'est pas la première fois qu'elle est fâchée avec les couleurs demandées, d'ailleurs... mais elle affiche de jolis soleils multicolores :D
User avatar
AfyuGénéreux
Niveau 12: CP (Calculatrice sur Pattes)
Niveau 12: CP (Calculatrice sur Pattes)
Level up: 9.3%
 
Posts: 122
Images: 3
Joined: 30 Oct 2019, 19:17
Gender: Male
Calculator(s):
Class: plutôt, oui :)

Online

Re: Mise à jour matplotlib Casio Graph 90/35+E II : arrow()

Unread postby cent20 » 18 Aug 2020, 14:25

Afyu wrote:
critor wrote:Bon la
NumWorks
semble ignorer les paramètres de couleur pour faire absolument n'importe quoi, mais ce n'est pas ce qui nous intéresse aujourd'hui.


C'est parce que la
NumWorks
c'est une rebelle :p

Il me semble que ce n'est pas la première fois qu'elle est fâchée avec les couleurs demandées, d'ailleurs... mais elle affiche de jolis soleils multicolores :D


Oui, ils sont juste jaloux, parce que nous on a de belles couleurs qui nous rappelle le printemps et éclairent l'écran de notre calculatrice :D
Image
Enseignant de mathématiques et de spécialité NSI ( projets, tutos ...)
:favorite: NumWork, Python : démineur, snake, tétris
User avatar
cent20Premium
Niveau 13: CU (Calculateur Universel)
Niveau 13: CU (Calculateur Universel)
Level up: 25.2%
 
Posts: 499
Images: 38
Joined: 17 May 2012, 09:49
Location: Avignon
Gender: Male
Calculator(s):
Twitter: nsi_xyz

Online

Re: Mise à jour matplotlib Casio Graph 90/35+E II : arrow()

Unread postby redgl0w » 18 Aug 2020, 14:30

Issue ouverte chez numworks (https://github.com/numworks/epsilon/issues/1647). Je vais essayer de fix ça cet aprèm
User avatar
redgl0wGénéreux
Niveau 10: GR (Guide de Référence)
Niveau 10: GR (Guide de Référence)
Level up: 84.2%
 
Posts: 94
Joined: 30 Oct 2019, 20:36
Gender: Male
Calculator(s):
Class: 2nde
GitHub: RedGl0w

Online

Re: Mise à jour matplotlib Casio Graph 90/35+E II : arrow()

Unread postby cent20 » 18 Aug 2020, 14:32

redgl0w wrote:Issue ouverte chez numworks (https://github.com/numworks/epsilon/issues/1647). Je vais essayer de fix ça cet aprèm


Mes couleurs :'( :'( :'(
Image
Enseignant de mathématiques et de spécialité NSI ( projets, tutos ...)
:favorite: NumWork, Python : démineur, snake, tétris
User avatar
cent20Premium
Niveau 13: CU (Calculateur Universel)
Niveau 13: CU (Calculateur Universel)
Level up: 25.2%
 
Posts: 499
Images: 38
Joined: 17 May 2012, 09:49
Location: Avignon
Gender: Male
Calculator(s):
Twitter: nsi_xyz

Online

Re: Mise à jour matplotlib Casio Graph 90/35+E II : arrow()

Unread postby redgl0w » 18 Aug 2020, 16:40

cent20 wrote:
redgl0w wrote:Issue ouverte chez numworks (https://github.com/numworks/epsilon/issues/1647). Je vais essayer de fix ça cet aprèm


Mes couleurs :'( :'( :'(

De quoi as-tu peur ?
Tes couleurs seront toujours là
User avatar
redgl0wGénéreux
Niveau 10: GR (Guide de Référence)
Niveau 10: GR (Guide de Référence)
Level up: 84.2%
 
Posts: 94
Joined: 30 Oct 2019, 20:36
Gender: Male
Calculator(s):
Class: 2nde
GitHub: RedGl0w

Re: Mise à jour matplotlib Casio Graph 90/35+E II : arrow()

Unread postby amigafred37 » 03 Sep 2020, 22:07

Merci pour ces corrections
User avatar
amigafred37Premium
Niveau 9: IC (Compteur Infatigable)
Niveau 9: IC (Compteur Infatigable)
Level up: 36.7%
 
Posts: 33
Joined: 05 Aug 2014, 01:01
Location: Tours
Gender: Male
Calculator(s):
Class: Loisirs & debutant


Return to News Casio

Who is online

Users browsing this forum: No registered users and 8 guests

-
Search
-
Featured topics
Comparaisons des meilleurs prix pour acheter sa calculatrice !
Découvre les nouvelles fonctionnalités en Python de l'OS 5.2 pour les Nspire CX II
Découvre les nouvelles fonctionnalités en Python de l'OS 5.5 pour la 83PCE/84+C-T Python Edition
Omega, le fork étendant les capacités de ta NumWorks, même en mode examen !
1234
-
Donations / Premium
For more contests, prizes, reviews, helping us pay the server and domains...

Discover the the advantages of a donor account !
JoinRejoignez the donors and/or premium!les donateurs et/ou premium !


Partner and ad
Notre partenaire Jarrety Calculatrices à acheter chez Calcuso
-
Stats.
610 utilisateurs:
>590 invités
>14 membres
>6 robots
Record simultané (sur 6 mois):
6892 utilisateurs (le 07/06/2017)

-
Other interesting websites
Texas Instruments Education
Global | France
 (English / Français)
Banque de programmes TI
ticalc.org
 (English)
La communauté TI-82
tout82.free.fr
 (Français)