+ Répondre à la discussion
Affichage des résultats 1 à 11 sur 11
  1. #1
    Rédacteur/Modérateur
    Avatar de Roland Chastain
    Homme Profil pro Roland Chastain
    Inscrit en
    décembre 2011
    Messages
    1 463
    Détails du profil
    Informations personnelles :
    Nom : Homme Roland Chastain
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : décembre 2011
    Messages : 1 463
    Points : 4 009
    Points
    4 009

    Par défaut Une console et ses fonctions

    En utilisant Algebrus j'ai eu l'idée de faire pour mes programmes Flash Pascal une console avec des instructions telles que Write(), ou même Info() ou ShowVec().

    Pour le moment j'en suis à chercher comment je pourrais m'y prendre. Voici mon premier essai :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    program essaiConsole;
     
    {$FRAME_WIDTH 640}
    {$FRAME_HEIGHT 300}
    {$FRAME_RATE 12}
    {$BACKGROUND $FFFFFF}
     
    uses
      Flash8;
     
    var
      t: textField;
      f: textFormat;
      a: array of string;
      i: integer;
     
    const
      l = 15;
     
    procedure initConsole;
    begin
      f := textFormat.create('Georgia', 16);
      f.color := $000088;
      t := textField.create(_root, 't', 0, 0, 0, 640, 300);
      t.setNewTextFormat(f);
    end;
     
    procedure writeLn(s: string);
    var
      i: integer;
    begin
      //
      a[Length(a)] := s;
      //
      if Length(a) <= l then
        t.text := t.text + a[Length(a)-1] + #13
      else
        begin
          t.text := '';
          for i := 0 to l - 1 do t.text := t.text + a[i + Length(a) - l] + #13;
        end;
    end;
     
    begin
      initConsole;
      for i := 1 to 20 do
        writeLn('ligne ' + intToStr(i));
    end.
    Je n'ai pas réussi à trouver une combinaison qui tombe juste entre la taille de la police, le nombre de lignes et la hauteur du champ.

    Sinon, le tableau de chaînes est-il une bonne idée ? Et d'utiliser un seul TextField ?

    J'ai vu dans l'unité Flash8 la propriété multiline. A quoi sert-elle exactement ?
    Fichiers attachés Fichiers attachés
    L'Art est long et le Temps est court.

  2. #2
    Expert Confirmé Sénior
    Avatar de Paul TOTH
    Homme Profil pro Paul TOTH
    Freelance
    Inscrit en
    novembre 2002
    Messages
    5 614
    Détails du profil
    Informations personnelles :
    Nom : Homme Paul TOTH
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : novembre 2002
    Messages : 5 614
    Points : 16 094
    Points
    16 094

    Par défaut

    Pour ce genre de chose il vaut mieux prendre une police non-proportionnelle comme "Courier New"

    sinon tu peux jouer avec une police Bitmap
    Presse-papiers-1.jpg

    mais ça pose quelque problème de clavier...
    console.zip
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Produits : UPnP, RemoteOffice, FlashPascal
    Embarcadero : Ile de la Réunion, Dephi, C++Builder, RADPHP...TVA à 8,5%

  3. #3
    Rédacteur/Modérateur
    Avatar de Roland Chastain
    Homme Profil pro Roland Chastain
    Inscrit en
    décembre 2011
    Messages
    1 463
    Détails du profil
    Informations personnelles :
    Nom : Homme Roland Chastain
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : décembre 2011
    Messages : 1 463
    Points : 4 009
    Points
    4 009

    Par défaut

    Oui, "Courier New", c'est mieux. J'ai fait la modification.

    J'aime beaucoup ton FlashDos.

    Et tout en étant amusant, c'est en même temps un exemple très utile. On peut en faire, des choses, avec une police Bitmap...
    L'Art est long et le Temps est court.

  4. #4
    Expert Confirmé Sénior
    Avatar de Paul TOTH
    Homme Profil pro Paul TOTH
    Freelance
    Inscrit en
    novembre 2002
    Messages
    5 614
    Détails du profil
    Informations personnelles :
    Nom : Homme Paul TOTH
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : novembre 2002
    Messages : 5 614
    Points : 16 094
    Points
    16 094

    Par défaut

    ah au fait, "multiline" c'est pour que la touche ENTREE permette de passer à la ligne dans un Textfield de type input
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Produits : UPnP, RemoteOffice, FlashPascal
    Embarcadero : Ile de la Réunion, Dephi, C++Builder, RADPHP...TVA à 8,5%

  5. #5
    Rédacteur/Modérateur
    Avatar de Roland Chastain
    Homme Profil pro Roland Chastain
    Inscrit en
    décembre 2011
    Messages
    1 463
    Détails du profil
    Informations personnelles :
    Nom : Homme Roland Chastain
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : décembre 2011
    Messages : 1 463
    Points : 4 009
    Points
    4 009

    Par défaut

    Citation Envoyé par Paul TOTH Voir le message
    ah au fait, "multiline" c'est pour que la touche ENTREE permette de passer à la ligne dans un Textfield de type input
    C'est pas mal !

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    program VotreNom;
     
    {$FRAME_WIDTH 640}
    {$FRAME_HEIGHT 300}
    {$FRAME_RATE 12}
    {$BACKGROUND $838383}
     
    uses
      Flash8;
     
    type
      TEditBox = class(TextField)
        procedure onKeyDown;
      end;
     
    var
      e: TEditBox;
      t: TextField;
      f1, f2: textFormat;
     
    procedure TEditBox.onKeyDown;
    begin
      if Key.getAscii = 13 then
      begin
        t.Text := e.Text;
      end;
    end;
     
    begin
      f1 := textFormat.create('Courier New', 16);
      f1.color := $008000;
      //
      f2 := textFormat.create('Courier New', 16);
      f2.color := $000080;
      //
      e := TEditBox.Create(_root, 'entree', 0, 10, 10, 620, 130);
      e.type := 'input';
      //
      e.multiline := true;
      //
      Selection.setFocus(e);
      Key.addListener(e);
      e.setNewTextFormat(f1);
      //
      t := TextField.Create(_root, 'sortie', 1, 10, 160, 620, 130);
      t.setNewTextFormat(f2);
     
      _root.opaqueBackground := $F8FCF8;
    end.
    Fichiers attachés Fichiers attachés
    L'Art est long et le Temps est court.

  6. #6
    Rédacteur/Modérateur
    Avatar de Roland Chastain
    Homme Profil pro Roland Chastain
    Inscrit en
    décembre 2011
    Messages
    1 463
    Détails du profil
    Informations personnelles :
    Nom : Homme Roland Chastain
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : décembre 2011
    Messages : 1 463
    Points : 4 009
    Points
    4 009

    Par défaut Traitement récursif d'une chaîne de caractères

    Bonsoir !

    J'ai repris mon projet d'une console pour des exercices de programmation avec Flash-Pascal. Par console j'entends une fenêtre avec entrée et sortie de texte. L'idée serait d'utiliser Flash-Pascal comme on utilise souvent JavaScript ou PHP, lorsqu'on veut permettre au visiteur d'une page d'essayer un programme.

    Le programme que je vous propose a un affichage en trois parties : un texte statique, une boîte d'entrée, un texte pour les résultats. La présentation est encore très perfectible, mais ça fonctionne.

    Vous remarquerez qu'on peut faire défiler les résultats avec la souris lorsqu'ils dépassent la capacité du TextField.

    Cet exemple pourrait aussi être l'occasion de revenir sur un sujet abordé il y a quelque temps dans une autre discussion, à savoir le traitement des tâches longues. Mon transpositeur fonctionne correctement jusqu'à 6 ou 7 caractères mais au-delà ça ne va plus.

    Vous me direz que la vocation de Flash-Pascal n'est pas d'effectuer des tâches longues, mais c'est toujours intéressant d'étudier le fonctionnement des choses.

    Transpositions.swf

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
     
    { Transpositions.pas
      Exemple Flash-Pascal
      R. Chastain }
     
    program Transpositions;
     
    uses
      Flash8;
     
    {$FRAME_WIDTH 600}
    {$FRAME_HEIGHT 400}
     
    type
      TEditBox = class(TextField)
        procedure onKeyDown;
      end;
     
    var
      e: TEditBox;
      t: TextField;
      s: string;
      c: integer;
     
    function Transpose(pS: string; n: integer): string;
    var
      temp: string;
      i, L: integer;
    begin
      temp := '';
    { Par exemple,
      si pS = 'abcde'
      et n = 3
      alors }
      L := Length(pS);
    { L = 5 }
      for i := 1 to L - n do temp := temp + pS[i];
    { temp = 'ab' }
      temp := temp + pS[l];
    { temp = 'ab' + 'e' }
      for i := L - n + 2 to L do temp := temp + pS[i - 1];
    { temp = 'abe' + 'cd' }
      result := temp;
    { result = 'abecd' }
    end;
     
    procedure Generateur(pS: string; n: integer);
    var
      i: integer;
      temp: string;
    begin
      temp := pS;
     
      for i := 1 to n do
      begin
        temp := Transpose(temp, n);
        if n = 1 then
        begin
          Inc(c);
          t.text := t.text + temp + ' ' + IntToStr(c) + #13
        end
        else
          Generateur(temp, n - 1);
      end;
    end;
     
    procedure TEditBox.onKeyDown;
    begin
      if Key.getAscii = 13 then
      begin
        s := e.text;
        t.text := ''; c := 0;
        Generateur(s, Length(s));
      end;
    end;
     
    begin
      with TextField.Create(_root, 'label', 0, 0, 0, Stage.Width-1, 4*16+4) do
      begin
        setNewTextFormat(TextFormat.Create('Courier New', 12));
        text := "Transpositions d'une chaîne de caractères."#13
              + 'Programme Flash-Pascal.'#13
              + 'Votre saisie ?';
      end;
     
      e := TEditBox.Create(_root, 'input', 1, 0, 3*16+4, Stage.Width-1, 16+4);
      e.setNewTextFormat(textFormat.Create('Courier New', 12));
      e.type := 'input';
      e.border := true;
      Selection.setFocus(e);
      Key.addListener(e);
     
      t := TextField.Create(_root, 'output', 2, 0, 3*16+4+16+4, Stage.Width-1,
                            Stage.Height - (3*16+4+16+4));
      t.SetNewTextFormat(TextFormat.Create('Courier New', 12));
      t.text := '';
      c := 0;
    end.
    L'Art est long et le Temps est court.

  7. #7
    Expert Confirmé Sénior
    Avatar de Paul TOTH
    Homme Profil pro Paul TOTH
    Freelance
    Inscrit en
    novembre 2002
    Messages
    5 614
    Détails du profil
    Informations personnelles :
    Nom : Homme Paul TOTH
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : novembre 2002
    Messages : 5 614
    Points : 16 094
    Points
    16 094

    Par défaut

    pour le coup c'est assez simple à paralléliser avec un timer, tu remplaces la boucle par le traitement de "n" itérations à chaque fois que le timer se déclenche, avec "n" suffisamment petit pour ne pas bloquer le tout.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Produits : UPnP, RemoteOffice, FlashPascal
    Embarcadero : Ile de la Réunion, Dephi, C++Builder, RADPHP...TVA à 8,5%

  8. #8
    Rédacteur/Modérateur
    Avatar de Roland Chastain
    Homme Profil pro Roland Chastain
    Inscrit en
    décembre 2011
    Messages
    1 463
    Détails du profil
    Informations personnelles :
    Nom : Homme Roland Chastain
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : décembre 2011
    Messages : 1 463
    Points : 4 009
    Points
    4 009

    Par défaut

    Je n'ai pas trouvé la solution (il me semble qu'il faudrait repenser tout le programme) mais j'ai retravaillé ma console. A la différence du code précédent, l'animation ne s'élargit pas aux dimensions du navigateur mais conserve une taille fixe.

    Code :
    stage.scaleMode := 'noScale';
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    program console_02;
     
    uses
      Flash8, Couleurs;
     
    {$FRAME_WIDTH 600}
    {$FRAME_HEIGHT 400}
    {$BACKGROUND $4169E1}
     
    const
      nomPrg = 'Console.'#13
             + 'Programme FlashPascal.';
      invite = 'Votre mot ?';
     
    type
      TEditBox = class(TextField)
        procedure onKeyDown;
      end;
     
    var
      e: TEditBox;
      t1, t2, t3: TextField;
      f1: TextFormat;
      sw, sh: Number;
     
    procedure TEditBox.onKeyDown;
    begin
      if Key.getAscii = 13 then
      begin
        t3.text := 'Votre mot est "' + e.text + '".';
      end;
    end;
     
    begin
      f1 := TextFormat.Create('Courier New', 13);
     
      sw := Stage.Width;
      sh := Stage.Height;
     
      t1 := TextField.Create(_root, 'nomPrg', 0, 0, 0*18, sw-1, 2*18);
      t1.setNewTextFormat(f1);
      t1.text := nomPrg;
     
      t2 := TextField.Create(_root, 'invite', 1, 0, 2*18, sw-1, 1*18);
      t2.setNewTextFormat(f1);
      t2.text := invite;
     
      e := TEditBox.Create(_root, 'I', 2, 0, 3*18, sw-1, 1*18);
      e.setNewTextFormat(f1);
      e.type := 'input';
      e.backgroundColor := Snow;
      e.background := true;
      e.borderColor := LightSteelBlue;
      e.border := true;
     
      Selection.setFocus(e);
      Key.addListener(e);
     
      t3 := TextField.Create(_root, 'O', 3, 0, 4*18, sw-1, sh-4*18);
      t3.SetNewTextFormat(f1);
      t3.text := '';
     
      _root.opaqueBackground := WhiteSmoke;
     
      stage.scaleMode := 'noScale';
    end.
    Fichiers attachés Fichiers attachés
    L'Art est long et le Temps est court.

  9. #9
    Membre Expert
    Avatar de Archimède
    Homme Profil pro anthony LAURENT
    Enseignant
    Inscrit en
    avril 2005
    Messages
    1 196
    Détails du profil
    Informations personnelles :
    Nom : Homme anthony LAURENT
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : avril 2005
    Messages : 1 196
    Points : 1 255
    Points
    1 255

    Par défaut

    Pour reprendre ton traitement récursif, il te faudrait une trame avec un timer de ce type là:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
     
    program Transpositions;
     
    uses
      Flash8;
     
    {$FRAME_WIDTH 600}
    {$FRAME_HEIGHT 400}
    {$FRAME_RATE 12}
    type
      TEditBox = class(TextField)
        procedure onKeyDown;
      end;
     
      TTransposition=class(movieclip)
       calcul:boolean;
       c,i: integer;
       s,temp: string;
       e: TEditBox;
       t: TextField;
       //....
       procedure onEnterFrame;override;
      end;
     
     
     
    constructor TTransposition.create;
    begin
     inherited create(_Root,'transposition',0);
     //constructeur e et t etc   aowner->self
     ..............
     ..............
     calcul:=false;.
     i:=0;
     //etc
     end;
     
    procedure TEditBox.onKeyDown;
    begin
      if (Key.getAscii = 13) and (length(e.text)<11) then calcul:=true; //limite la chaîne à 10 par exemple(il faut tester je n'en sais rien)
    end;
     
    procedure TTransposition.onEnterFrame;
    begin
       if calcul then
       begin
         inc(i);
         if i<=Length(e.text) Then
          begin
           //ton traitement
          end
          else
          begin
           calcul:false;
           i:=0;
          end;
        end;
    end;
     
    //etc procedure de traitement
     
    begin
     TTransposition.Create;
    end.
    Si ça peut t'aider à avancer... je n'ai pas le temps de décortiquer ton code...

  10. #10
    Rédacteur/Modérateur
    Avatar de Roland Chastain
    Homme Profil pro Roland Chastain
    Inscrit en
    décembre 2011
    Messages
    1 463
    Détails du profil
    Informations personnelles :
    Nom : Homme Roland Chastain
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : décembre 2011
    Messages : 1 463
    Points : 4 009
    Points
    4 009

    Par défaut

    Merci pour ton code ! Je vais l'étudier.
    L'Art est long et le Temps est court.

  11. #11
    Rédacteur/Modérateur
    Avatar de Roland Chastain
    Homme Profil pro Roland Chastain
    Inscrit en
    décembre 2011
    Messages
    1 463
    Détails du profil
    Informations personnelles :
    Nom : Homme Roland Chastain
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : décembre 2011
    Messages : 1 463
    Points : 4 009
    Points
    4 009

    Par défaut

    Bonsoir !

    Je n'ai pas résolu le problème des transpositions. J'y reviendrai plus tard.

    Voici le dernier état de mon projet. Cette fois c'est un programme qui convertit un nombre décimal en fraction. Je précise que ce n'est pas le même programme que celui que j'ai posté . La méthode de recherche est entièrement différente.

    J'ai séparé mon projet en deux fichiers. Le code relatif aux fractions se trouve dans une unité, Fraction.pas, et l'interface se trouve dans le fichier Console.fpr. On dirait presque un projet Delphi.

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    program Console;
     
    {$FRAME_WIDTH 400}
    {$FRAME_HEIGHT 240}
     
    uses
      Flash8, Fraction;
     
    type
      tEditBox = class(textField)
        procedure onKeyDown;
      end;
     
    var
      S1,
      S2: textField;  // sortie
      E1: tEditBox;   // entrée
      F1: textFormat; // format
     
    procedure tEditBox.onKeyDown;
    var
      i: integer;
    begin
      if key.getAscii = 13 then
      begin
        S2.text := Fraction.F(E1.text);
      end;
    end;
     
    begin
      F1 := TextFormat.create('Courier New', 14);
     
      S1 := textField.Create(_root, 'sortie_1', 0, 0, 0, stage.width-1, 3*20);
      S1.SetNewTextFormat(F1);
      S1.text := "FlashPascal 2 v12.07.07."#13
               + "Conversion d'un nombre décimal en fraction."#13
               + "Veuillez saisir un nombre décimal:";
     
      E1 := tEditBox.Create(_root, 'entree_1', 1, 0, 3*20, stage.width-1, 20);
      E1.setNewTextFormat(F1);
      E1.type := 'input';
      E1.border := TRUE;
      E1.borderColor := $e0e0e0;
      selection.setFocus(E1);
      key.addListener(E1);
     
      S2 := textField.Create(_root, 'output', 2, 0, 4*20, stage.width-1,
        stage.height-(4*20));
      S2.SetNewTextFormat(F1);
     
      stage.scaleMode := 'noScale';
    end.
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    unit Fraction;
     
    { Conversion d'un nombre décimal en fraction. }
     
     
    interface
     
    uses
      Flash8;
     
    function F(s: string): string;
     
     
    implementation
     
    function StrToFloat(expression: string): Number external 'parseFloat';
     
    function PGCD(a, b: integer): integer;
    begin
      if b = 0 then
        Result := a
      else
        Result := PGCD(b, a mod b);
    end;
     
    function F(s: string): string;
    var
    { nombre à convertir }
      n: number;
    { numérateur, dénominateur }
      i, j: integer;
    { nombre de chiffres après la virgule }
      k: integer;
    { variable à tout faire }
      l: integer;
    begin
      n := StrToFloat(s);
     
      k := Length(s) - (Pos('.', s) + 1);
     
      j := 1;
      for l := 1 to k do
        j := 10 * j;
     
      i := Trunc(Math.Round(n * j));
     
      Result := "Résultat 1 : " + IntToStr(i) + '/' + IntToStr(j) + #13;
     
      l := PGCD(i, j);
     
      i := i div l;
      j := j div l;
     
      Result := Result + "Résultat 2 : " + IntToStr(i) + '/' + IntToStr(j);
    end;
     
     
    end.
    Images attachées Images attachées
    Fichiers attachés Fichiers attachés
    L'Art est long et le Temps est court.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •