JsConsole.Net– Console javascript déportée pour le déboggage

J’ai développé cette petite application Windows pour me permettre lors du débogage d’applications web, de visualiser la console JavaScript de manière déportée. Sur certains devices, comme la plupart des consoles de jeux, il n’est pas possible d’accéder à cette console de débogage.

L’application a été développée en C# et WPF  pour l’interface utilisateur et utilise le pattern MVVM indispensable au découpage fonctionnel du code.
Concernant les fonctionnalités un serveur web Owin permet l’auto hébergement des applications web au sein du répertoire « /Web » qui se trouve a la racine de l’application. Par contre, Owin nécessite une élévation de privilège pour ouvrir des sockets réseaux au niveau d’une IP externe, l’application lors de l’exécution vous demandera donc une autorisation plus élevée lors du lancement.
Il est possible aussi d’écrire des bouts de codes « snippet » en créant des fichiers avec l’extension js dans le répertoire « /snippet » ceux-ci pourront être directement inséré dans la console d’exécution des scripts.
Le but de cette application était aussi  pour moi, de mettre en pratique certains frameworks comme l’association entre AngularJs et SignalR.
Par la suite, j’ai inclus une fonctionnalité d’intelliSence lorsque l’on tape du code JavaScript, ce qui m’a semblé bien pratique pour un développeur. Pour cela, la bibliothèque la plus aboutie est AvalonEdit, malheureusement celle-ci n’est pas compatible avec MVVM. Il faut donc faire un peu de code dans la partie code behind, je n’aime pas trop, mais je pense que dans une prochaine version j’essayerai de la rendre compatible MVVM, soit en créant une classe qui hérite des classes d’avalonEdit ou un behavior ou encore avec une attached propertie.

Ce projet a été développé avec les librairies suivantes
–    AvalonEdit
–    MahApps
–    Owin
–    Mvvm Light Toolkit
–    AngularJS
–    SignalR
–    Bootstrap

Voiçi une vidéo, pour comprendre l’utilisation de l’application :

Le code est disponible ici : https://github.com/auriou/JsConsole.Net

, , ,

Poster un commentaire

VideoCast : Extension Chrome pour la Chromecast et VLC

Je viens de publier sur le store de Chrome, une nouvelle extension qui vous permet de diffuser les vidéos trouvez sur le web soit sur la Chromecast ou VLC ou encore le player intégré. Cette extension va capturer et historiser les vidéos que vous lancerez sur chrome.

Extensions vidéos prises en charge :
  -Player intégré et chromecast : mp4, webm
  -VLC : mp4, webm, flv

https://chrome.google.com/webstore/detail/videocast/gclhodkofgoighinmongpkpncdpalejb

videocast-screen-market

, , , , ,

3 Commentaires

Extension Chrome permettant de visualiser les vidéos web sur VLC

https://chrome.google.com/webstore/detail/vlc-capture/goppbgmjnldonmjemebdmcjfefbgoloh

Voici une extension que j’ai développée permettant de visualiser sur VLC les vidéos ouvertes dans le navigateur Chrome.

Il suffit de lancer une vidéo dans un onglet pour que celle-ci soit jouée sur VLC.

Un historique des consultations est conservé et accessible en cliquant sur l’icône de l’extension.

Pour que la vidéo soit jouée directement il faut que VLC soit lancé et configuré au préalable l’interface Web dans VLC.

Menu VLC > Outils > Préférences > Choisir l’interface avancée (en bas, à gauche cocher l’option “Tous”) > Interfaces principales > Cocher “Web”

preference-vlc

 

La capture des vidéos peut être arrêtée en ouvrant le menu en cliquant sur l’icône VLC puis en décochant la capture vidéo.

vlc-capture-ext

J’ai développé cette extension, car les développeurs de VLC sont en train d’ajouter la possibilité de caster les flux vidéos sur la Google Chromecast et comme j’en possède une, cela m’intéresse de voir n’importe quelle vidéo sur ma télévision au travers de VLC et de la Chromecast.

Extension >> https://chrome.google.com/webstore/detail/vlc-capture/goppbgmjnldonmjemebdmcjfefbgoloh

, , , ,

3 Commentaires

FIGlet.Net – Génération et OCR de Textes Art ASCII

Lors d’un challenge informatique qui avait pour but de répondre à un robot sur un canal IRC, j’ai dû développer un programme qui devait reconnaitre des textes aléatoires écrits en Art ASCII en moins d’une seconde et il dévait renvoyer le résultat sur le canal IRC. Cette technique d’écriture de texte était très répandue par le passé sur les mainframes, les BBS, puis sur beaucoup d’applications en mode texte ce qui est encore le cas pour les serveurs IRC.

Une librairie permettant d’écrire ces textes développée en C, existe pour les systèmes Unix . Elle définit un format de fichier de police de caractère. Ce programme est FIGlet et les fichiers de polices ont pour extension .flf .

Mon langage de prédilections étant le C#, j’ai donc développé une version FIGlet.Net et comme j’avais besoin pour ce challenge de lire ce type de texte, j’ai créé une fonction de reconnaissance de caractères des textes Art-ASCII.

Voici un exemple :

artascii

Et le code client, pour utiliser la librairie :

namespace FIGlet.Net
{
    public class SampleClient
    {
        public static void TestUsage()
        {
            var fig = new Figlet(); //font par défaut
            //Chargement d'une font spécifique au format Figlet
            //fig.LoadFont(@"D:\FIGLET\FONTS\standard.flf");

            //Génération et affichage du texte  Art ASCII
            var asciiart = fig.ToAsciiArt("Microsoft.Net");
            Console.WriteLine(asciiart);

            //Préparation d'un alphabet pour la reconnaissance de l'image Art ASCII
            fig.PrepareAlphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.");
            //Reconnaissance de l'image et affichage du texte trouvé
            var reconize = fig.ReconizeAsciiArt(asciiart);
            Console.WriteLine("Résultat OCR-ArtASCII: {0}",reconize);
            Console.ReadLine();
        }
    }
}

J’ai publié le code de ma librairie FIGlet.Net sur GitHub si vous etes intéressé c’est ici :  https://github.com/auriou/FIGlet

, ,

Poster un commentaire

WPF : HighlightConverter (IMultiValueConverter)

Lorsque l’on met en place une zone de recherche, il est intéressant de mettre en surbrillance les zones qui correspondent dans le résultat de votre recherche.

Voiçi une interface que j’ai réalisée pour un projet :

HighlightConverter[1]

Mon treeView est bindé à une collection spécialisée “class TreeList<T> : ObservableCollection<TreeNode<T>>, INotifyPropertyChanged ” dans laquelle je manipule les propriétes pour ouvrir / fermer / cacher / afficher les noeuds de la treeview. Le binding est le  suivant.

<Style x:Key="TreeViewItemStyle" TargetType="{x:Type TreeViewItem}">
  <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
  <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
  <Setter Property="Visibility" Value="{Binding IsHidden, Converter={StaticResource ResourceKey=InverseBoolToVisibilityConverter}}" />

Le résultat d’une recherche sera un textBlock comprenant un champ de type Run avec un style différent pour identifier le texte trouvé.

Il sera donc nécessaire d’avoir 3 objets Run :     

– Start  :  début du résultat qui peut être vide,

– Find  :  partie du résulat comprenand le terme de la recherche, identifié en rouge,

– End   :  fin du résultat qui peut etre vide 

Comme il y à 2 binding pour déterminer le résultat à renvoyer, il faudra donc un converter Multi-valué

 

        <TextBlock>
          <TextBlock.Inlines>
            <Run>
              <Run.Text>
                <MultiBinding Converter="{StaticResource HighlightConverter}" ConverterParameter="Start">
                  <Binding Mode="OneWay" Path="DisplayText" />
                  <Binding ElementName="SearchBox"
                           Mode="OneWay"
                           Path="DataContext.SearchCompteGeneral" />
                </MultiBinding>
              </Run.Text>
            </Run>
            <Run Style="{DynamicResource HighlightStyle}">
              <Run.Text>
                <MultiBinding Converter="{StaticResource HighlightConverter}" ConverterParameter="Find">
                  <Binding Mode="OneWay" Path="DisplayText" />
                  <Binding ElementName="SearchBox"
                           Mode="OneWay"
                           Path="DataContext.SearchCompteGeneral" />
                </MultiBinding>
              </Run.Text>
            </Run>
            <Run>
              <Run.Text>
                <MultiBinding Converter="{StaticResource HighlightConverter}" ConverterParameter="End">
                  <Binding Mode="OneWay" Path="DisplayText" />
                  <Binding ElementName="SearchBox"
                           Mode="OneWay"
                           Path="DataContext.SearchCompteGeneral" />
                </MultiBinding>
              </Run.Text>
            </Run>
          </TextBlock.Inlines>
        </TextBlock>

 

Maintenant le code du converter multi-valué :

 

public class HighlightConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var value = System.Convert.ToString(values[0]);
        var terms = System.Convert.ToString(values[1]);
        var param = System.Convert.ToString(parameter);

        if (!string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(terms))
        {
            if (value.ToLower().Contains(terms.ToLower()))
            {
                var findIndex = value.ToLower().IndexOf(terms.ToLower(), System.StringComparison.Ordinal);
                switch (param)
                {
                    case "Start":
                        return value.Substring(0, findIndex);
                    case "Find":
                        return value.Substring(findIndex, terms.Length);
                    case "End":
                        return value.Substring(findIndex + terms.Length);
                }
            }
        }
        if (param == "Start")
        {
            return value;
        }
        return "";
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        return null;
    }
}

 

Le code Xaml avec la treeVIew:

<Grid x:Name="GridSearchCompte" Grid.Row="1">
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <TextBox Name="SearchBox"
           Margin="5,2"
           HorizontalAlignment="Stretch"
           VerticalAlignment="Stretch"
           Text="{Binding Path=SearchCompteGeneral,
                            Delay=700,
                            Mode=TwoWay,
                            UpdateSourceTrigger=PropertyChanged}"
           controls:TextboxHelper.ClearTextButton="True"
           controls:TextboxHelper.Watermark="Recherche rubrique">
    <TextBox.Style>
      <Style BasedOn="{StaticResource SearchMetroTextBox}" TargetType="{x:Type TextBox}">
        <Style.Triggers>
          <Trigger Property="controls:TextboxHelper.HasText" Value="True">
            <Setter Property="controls:TextboxHelper.ButtonTemplate" Value="{DynamicResource ChromelessButtonTemplate}" />
          </Trigger>
        </Style.Triggers>
      </Style>
    </TextBox.Style>
  </TextBox>
  <TextBlock Grid.Row="1"
             Margin="5,0"
             HorizontalAlignment="Right"
             FontSize="12"
             Foreground="{DynamicResource ColorBleu}"
             Text="{Binding TreeRubriques.SelectedItem}" />
  <TreeView Name="TreeViewGeneral"
            Grid.Row="2"
            ItemContainerStyle="{DynamicResource TreeViewItemStyle}"
            ItemsSource="{Binding Path=TreeRubriques}">
    <TreeView.ItemTemplate>
      <HierarchicalDataTemplate ItemsSource="{Binding Children}">
        <TextBlock>
          <TextBlock.Inlines>
            <Run>
              <Run.Text>
                <MultiBinding Converter="{StaticResource HighlightConverter}" ConverterParameter="Start">
                  <Binding Mode="OneWay" Path="DisplayText" />
                  <Binding ElementName="SearchBox"
                           Mode="OneWay"
                           Path="DataContext.SearchCompteGeneral" />
                </MultiBinding>
              </Run.Text>
            </Run>
            <Run Style="{DynamicResource HighlightStyle}">
              <Run.Text>
                <MultiBinding Converter="{StaticResource HighlightConverter}" ConverterParameter="Find">
                  <Binding Mode="OneWay" Path="DisplayText" />
                  <Binding ElementName="SearchBox"
                           Mode="OneWay"
                           Path="DataContext.SearchCompteGeneral" />
                </MultiBinding>
              </Run.Text>
            </Run>
            <Run>
              <Run.Text>
                <MultiBinding Converter="{StaticResource HighlightConverter}" ConverterParameter="End">
                  <Binding Mode="OneWay" Path="DisplayText" />
                  <Binding ElementName="SearchBox"
                           Mode="OneWay"
                           Path="DataContext.SearchCompteGeneral" />
                </MultiBinding>
              </Run.Text>
            </Run>
          </TextBlock.Inlines>
        </TextBlock>
      </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
  </TreeView>
</Grid>

,

Poster un commentaire

Convertir du Json et XML en classes C# fortement typées

Visual studio 2012, offre la possibilité de convertir des données XML ou Json en classe C# fortement typée. Quand l’on doit interagir avec des services REST comme les API de google, il est intéressant de pouvoir utiliser le nom des objets dans son code et ainsi éviter d’utiliser un parser XML ou Json.

Pour que cela fonctionne, il faut être dans un projet utilisant le framework .net 4.5

  1. Copier une source XML ou Json dans le presse-papier (Ctrl+A – Ctrl+C)
    1-convertxml
  2. Se placer dans un fichier de code
    2-convertxml
  3. Ouvrir le menu Edition > Collage spécial > Coller XML sous forme de classes
    3-convertxml
  4. Voilà la classe fortement typée créée
    4-convertxml
  5. Voici une classe d’extension pour simplifier la sérialisation des objets
    using Newtonsoft.Json;
    using System.IO;
    using System.Text;
    using System.Xml.Serialization;
    
    namespace SampleCopyObject
    {
        public static class Deserializer
        {
            //nécessite le package nuget : Json.Net http://james.newtonking.com/json
            public static T DeserializeJson<T>(this string strObject)
            {
                return JsonConvert.DeserializeObject<T>(strObject);
            }
            public static T DeserializeXml<T>(this string strObject)
            {
                var stream = strObject.ToStream();
                var serializer = new XmlSerializer(typeof(T));
                return (T)serializer.Deserialize(stream);
            }
            public static Stream ToStream(this string strObject)
            {
                var byteArray = Encoding.UTF8.GetBytes(strObject);
                return new MemoryStream(byteArray);
            }
        }
    }
  6. Solution de test
    using System.Net;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using SampleCopyObject;
    
    namespace SampleCopyObject.Test
    {
        [TestClass]
        public class UnitTestDeserialiser
        {
            [TestMethod]
            public void TestXml()
            {
                const string xmlFile = "http://www.dreamincode.net/forums/xml.php?showuser=1253";
                var client = new WebClient();
                var strObject = client.DownloadString(xmlFile);
                var result = strObject.DeserializeXml<ipb>();
                Assert.IsNotNull(result);
                Assert.IsNotNull(result.profile);
            }
            [TestMethod]
            public void TestJson()
            {
                const string jsonFile = "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=test";
                var client = new WebClient();
                var strObject = client.DownloadString(jsonFile);
                var result = strObject.DeserializeJson<Rootobject>();
                Assert.IsNotNull(result);
                Assert.IsNotNull(result.responseData);
            }
        }
    }

Poster un commentaire

Grouper vos fichiers dans visual studio 2012

Dans un projet WPF, Silverlight ou Window Store (WinRT), si l’on utilise le patron de conception MVVM (Model / Vue / VueModel) nous regrouperons les vues dans un répertoire, le plus souvent nommé Views, elles mêmes composées d’un fichier XAML et d’un fichier CS pour le code behind. Pour chacune de ces vues correspond une classe manipulant le model métier, ces fichiers sont placés dans un autre répertoire appelé ViewModels.

Dans un gros projet, cela devient vite compliqué de jongler dans l’explorateur de solution entre la Vue Xaml et le ViewModel.

Il existe une autre possibilitée pour organiser son code, qui est utilisé dans les exemples du framework PRISM. Ce framework permet d’implémenter le pattern MVVM (Command/Message), simplifie le développement d’applications composites, et prend en charge la navigation. Dans les exemples fournis, le choix a été de placer les vues et les vues-modèles dans des répertoires communs par thème fonctionnel.

Je trouve cette pratique plus intuitive, étant donné que Vue et vues-modèles sont complètement liées. Pour aller plus loin dans ce raisonnement, il serait intéressant de regrouper le vue-modèl sous la vue comme c’est déjà le cas pour le code-behind du fichier XAML.

Une extension de visual studio permet de faire cela très simplement, il s’agit de  VSCommand

  • Résultat des regroupements sous chacune des vues

resultat

  1. Installer l’extension VSCommand
    Extension
  2. Sélectionner les fichiers à regrouper > menu contextuel > choisir le menu Group Items

    MenuGroup
  3. Valider la fenêtre suivante
    WindowSelect
  4. Voila les fichiers groupés sous la vue
    ResultatJoin

Poster un commentaire

La logique floue (fuzzy logic) – Exemple en C# avec Aforge.Fuzzy

Introduction

La logique floue est un domaine de l’intelligence artificielle, elle se rapproche du raisonnement humain. Contrairement à des calculs rigides, qui se base sur des ensembles bien définis, elle utilise des ensembles flous ou imprécis. Elle s’appuie sur la théorie mathématique des ensembles flous qui est une extension de la théorie des ensembles.

Pour vous montrer l’utilisation de la bibliothèque .Net Aforge.Net, nous allons nous baser sur l’exemple décris dans l’excellent article de Franck Dernoncourt que je vous invite à lire : http://franck-dernoncourt.developpez.com/tutoriels/algo/introduction-logique-floue/

L’objectif sera de décider du pourboire à donner à la fin d’un repas au restaurant en fonction de la qualité du service ainsi que de la qualité de la nourriture.

Étapes pour définir un système flou

Représentation d’un système d’inférence avec Aforge.net

Fig4

  • Input et Output

Il est nécessaire dans un premier temps de définir les différentes entrées et sorties du système :

    • Input    : Nourriture          =   noté sur une échelle de  0 à 10
    • Input    : QualiteService    =   noté sur une échelle de  0 à 10
    • Output : Pourboire           =    montant donné de 0 à 30 euros

Code avec la librairie Aforge.Net :

var lvNourriture = new LinguisticVariable("Nourriture", 0, 10);
    var lvQualiteService = new LinguisticVariable("QualiteService", 0, 10);
    var lvPourboire = new LinguisticVariable("Pourboire", 0, 30);

  • La Fuzzification

Nous devons définir des variables dites “variables linguistiques” qui seront utilisées pour définir les règles du système. Il y a ici 3 variables linguistiques  : Nourriture, QualiteService, Pourboire.

Pour chacune de ces variables, il est nécessaire de qualifier les éléments de ces ensembles flous

    • Input    : Nourriture          =   {Execrable, Delicieux}
    • Input    : QualiteService  =   {Mauvais, Bon, Excellent}
    • Output : Pourboire           =   {Faible, Moyen, Eleve)}

Pour chacun de ces éléments il est nécessaire de lui adjoindre une fonction d’appartenance, le plus souvent définie par des segments de droites.

is-var-nourriture

Code avec Aforge.Net :  les fonctions trapézoïdales ont plusieurs constructeurs, ici le trapèze est ouvert sur la droite, puis sur la gauche en formant une ligne infinie.

//Trapèze avec ligne infinie sur la droite
    var fsExecrable = new FuzzySet("Execrable", new TrapezoidalFunction(1, 3, TrapezoidalFunction.EdgeType.Right));
    //Trapèze avec ligne infinie sur la gauche
    var fsDelicieux = new FuzzySet("Delicieux", new TrapezoidalFunction(7, 9, TrapezoidalFunction.EdgeType.Left));

Exemple: une note pour la qualité de la nourriture de 1 est considérée comme exécrable; une note de 2 est considéré comme 50% exécrable; et 3 sort du périmètre de ce qualificatif.

is-var-service

Code avec Aforge.Net :

var fsMauvais = new FuzzySet("Mauvais", new TrapezoidalFunction(0, 5, TrapezoidalFunction.EdgeType.Right));
    var fsBon = new FuzzySet("Bon", new TrapezoidalFunction(0, 5, 10));
    var fsExcellent = new FuzzySet("Excellent", new TrapezoidalFunction(5, 10, TrapezoidalFunction.EdgeType.Left));

Exemple: Pour la qualité de service, une note de 5 est considérée comme 100% bon, une note de 8,5 est considérée comme 50% excellent.

is-var-pourboire

Code avec Aforge.Net :

var fsFaible = new FuzzySet("Faible", new TrapezoidalFunction(0, 5, 10));
    var fsMoyen = new FuzzySet("Moyen", new TrapezoidalFunction(10, 15, 20));
    var fsEleve = new FuzzySet("Eleve", new TrapezoidalFunction(20, 25, 30));

Exemple: Pour le pourboire, un montant de 5 € est 100% faible, 22.5€ est considéré comme 50% élevé.

Il faut maintenant associer les qualificatifs aux différents ensembles flous :

    lvNourriture.AddLabel(fsExecrable);  //Ajout du qualificatif exécrable à l’ensemble flou Nourriture
    lvNourriture.AddLabel(fsDelicieux);  //Ajout du qualificatif délicieux à l’ensemble flou Nourriture 
    lvQualiteService.AddLabel(fsMauvais); //Ajout du qualificatif mauvais à l’ensemble flou Qualité de service
    lvQualiteService.AddLabel(fsBon);     //Ajout du qualificatif bon à l’ensemble flou Qualité de service
    lvQualiteService.AddLabel(fsExcellent); //Ajout du qualificatif excellent à l’ensemble flou Qualité de service 
    lvPourboire.AddLabel(fsFaible); //Ajout du qualificatif faible à l’ensemble flou Pourboire 
    lvPourboire.AddLabel(fsMoyen);  //Ajout du qualificatif moyen à l’ensemble flou Pourboire 
    lvPourboire.AddLabel(fsEleve);  //Ajout du qualificatif élevé à l’ensemble flou Pourboire 
  • Base de connaissance

Nous allons créer une base regroupant les variables linguistiques créées juste avant.

var fuzzyDb = new Database();      //Création de la base 
    fuzzyDb.AddVariable(lvNourriture); //Ajout des variables linguistiques
    fuzzyDb.AddVariable(lvQualiteService);
    fuzzyDb.AddVariable(lvPourboire);
  • Initialisation du système d’inférence

// Création system inference
    // Initialise la méthode de défuzzification : centre de gravité
    var inferenceSys = new InferenceSystem(fuzzyDb, new CentroidDefuzzifier(1000));

Le constructeur a besoin de la base regroupant l’ensemble des variables linguistiques et d’une méthode de défuzzification.

  • Définition des règles floues

les règles du système sont les suivantes :

    • Si le service est mauvais ou la nourriture est exécrable alors le pourboire est faible.
    • Si le service est bon alors le pourboire est moyen.
    • Si le service est excellent ou la nourriture est délicieuse alors le pourboire est élevé.

Ce qui se traduit en code par :

    inferenceSys.NewRule("Rule 1", "IF QualiteService IS Mauvais OR Nourriture IS Execrable THEN Pourboire IS Faible");
    inferenceSys.NewRule("Rule 2", "IF QualiteService IS Bon THEN Pourboire IS Moyen");
    inferenceSys.NewRule("Rule 3", "IF QualiteService IS Excellent OR Nourriture IS Delicieux THEN Pourboire IS Eleve");
  • Défuzzification & Output

// Initialise les données d'entrées
    inferenceSys.SetInput("QualiteService", noteQualiteService);
    inferenceSys.SetInput("Nourriture", noteNourriture);
    // Evalue la donnée de sortie : Pourboire = Output
    resPourboire = inferenceSys.Evaluate("Pourboire");


Source complète de l’exemple :

static void Main(string[] args)
{
WritePourboire(7, 9);
    WritePourboire(2, 9);
    WritePourboire(5, 6);
    WritePourboire(2, 3);
    Console.ReadLine();
}

public static void WritePourboire(float noteQualiteService, float noteNourriture)
{
    #region Input (Qualité de service)
    var lvQualiteService = new LinguisticVariable("QualiteService", 0, 10);

    var fsMauvais = new FuzzySet("Mauvais", new TrapezoidalFunction(0, 5, TrapezoidalFunction.EdgeType.Right));
    var fsBon = new FuzzySet("Bon", new TrapezoidalFunction(0, 5, 10));
    var fsExcellent = new FuzzySet("Excellent", new TrapezoidalFunction(5, 10, TrapezoidalFunction.EdgeType.Left));

    lvQualiteService.AddLabel(fsMauvais);
    lvQualiteService.AddLabel(fsBon);
    lvQualiteService.AddLabel(fsExcellent);
    #endregion

    #region Input (Nourriture)
    var lvNourriture = new LinguisticVariable("Nourriture", 0, 10);

    var fsExecrable = new FuzzySet("Execrable", new TrapezoidalFunction(1, 3, TrapezoidalFunction.EdgeType.Right));
    var fsDelicieux = new FuzzySet("Delicieux", new TrapezoidalFunction(7, 9, TrapezoidalFunction.EdgeType.Left));

    lvNourriture.AddLabel(fsExecrable);
    lvNourriture.AddLabel(fsDelicieux);
    #endregion

    #region Output (Pourboire)
    var lvPourboire = new LinguisticVariable("Pourboire", 0, 30);

    var fsFaible = new FuzzySet("Faible", new TrapezoidalFunction(0, 5, 10));
    var fsMoyen = new FuzzySet("Moyen", new TrapezoidalFunction(10, 15, 20));
    var fsEleve = new FuzzySet("Eleve", new TrapezoidalFunction(20, 25, 30));

    lvPourboire.AddLabel(fsFaible);
    lvPourboire.AddLabel(fsMoyen);
    lvPourboire.AddLabel(fsEleve);
    #endregion

    #region Système Inference
    // Base de données pour les variables linguistiques
    // Nourriture(Execrable, Delicieux) 0 - 10
    // QualiteService(Mauvais, Bon, Excellent) 0 - 10
    // Pourboire(Faible, Moyen, Eleve) 0 - 30
    var fuzzyDb = new Database();
    fuzzyDb.AddVariable(lvNourriture);
    fuzzyDb.AddVariable(lvQualiteService);
    fuzzyDb.AddVariable(lvPourboire);

    // Creation system inference
    // Initialise la methode de défuzzification : centre de gravité
    var inferenceSys = new InferenceSystem(fuzzyDb, new CentroidDefuzzifier(1000));
    // Ajoute des regles
    inferenceSys.NewRule("Rule 1", "IF QualiteService IS Mauvais OR Nourriture IS Execrable THEN Pourboire IS Faible");
    inferenceSys.NewRule("Rule 2", "IF QualiteService IS Bon THEN Pourboire IS Moyen");
    inferenceSys.NewRule("Rule 3", "IF QualiteService IS Excellent OR Nourriture IS Delicieux THEN Pourboire IS Eleve");
    #endregion

    #region Exemple
    // Initialise les données d'entrées
    inferenceSys.SetInput("QualiteService", noteQualiteService);
    inferenceSys.SetInput("Nourriture", noteNourriture);

    // Evalue la donnée de sortie : Pourboire
    var resPourboire = -1f;
    try
    {
        resPourboire = inferenceSys.Evaluate("Pourboire");
    }
    catch (Exception ex)
    {
        throw new Exception(string.Format("Erreur : {0}", ex.Message));
    }
    Console.WriteLine("Nourriture: {0}  + QualiteService : {1} = Pourboire : {2}", 
        noteNourriture, noteQualiteService, resPourboire);
    #endregion
}

Sortie du programme :

Nourriture: 9  + QualiteService : 7 = Pourboire : 20,43472
Nourriture: 9  + QualiteService : 2 = Pourboire : 15,64511
Nourriture: 6  + QualiteService : 5 = Pourboire : 14,99998
Nourriture: 3  + QualiteService : 2 = Pourboire : 9,324404

Poster un commentaire

Les patterns de construction dans le framework.Net

Les patterns de construction ont pour rôle de masquer la complexité de création des objets et de rendre le système indépendant du processus d’instanciation des classes. Pour ce faire ces patterns privilégient l’utilisation des Interfaces ou des classes abstraites dans la relation entre les objets en masquant les classes concrètes au client final.

Le choix entre Classe Abstraite et Interface ?

– Choisir une classe abstraite si la classe doit contenir des comportements par défauts, comme par exemple une méthode codée dans la classe abstraite qui pourra être utilisée par l’ensemble des classes concrètes.

– Choisir une interface si toutes les classes concrètes ont leurs propres implémentations.

  • Définition des Patterns de créations :

  1. Abstract Factory : Ce modèle fournit une interface pour créer des familles d’objets liés ou dépendants sans spécifier leurs classes concertes. Créer des objets, de classes abstraites différentes, mais de mêmes familles de classes concrètes. L’abstract factory ne fait rien d’autre que de créer des objets à la différence du pattern Factory Method. Dans ce pattern il faut utiliser un singleton pour n’avoir q’une seule instance de chacune des fabriques concrètes.
  2. Factory Method : Permets de déléguer aux sous-classes l’instanciation au travers d’une méthode abstraite de création des objets. L’appel du constructeur des sous-classe peut être fait en passant un paramètre a la Factory Method. La différence avec Abstract Factory, est que la classe possède d’autres responsabilités que le simple fait de créer des objets.
  3. Singleton : Ce modèle garantit qu’une classe n’a qu’une seule instance et fournit un point d’accès à celle çi.
  4. Builder : Permet d’abstraire la construction d’objets complexe : objets composés – par exemple la fenêtre d’une application composée de différents menus, d’un titre, etc. Sans se soucier par exemple du style de rendu (menu classique, Ruban office …)
  5. Prototype : Il est utilisé pour créer un objet en double ou clone de l’objet courant.
  • Patterns de créations dans le framework.Net :

Voici un exemple de code C# utilisant les 5 types de pattern de conception présent dans le framework.net :

public int DbProviderFactoryPatterns()
{
    // 1 - Abstract Factory : Classes concrètes SQL.. / ODBC.. / OLEDB..
    // Familles de produits : Connection / Command, etc. Commence par CreateXXX
    var dbProviderFactory = DbProviderFactories.GetFactory("System.Data.SqlClient");// 2 - Factory Method

    var dbConnection = dbProviderFactory.CreateConnection();                        // 3 - Factory Method

    var singletonSqlClientFactory = SqlClientFactory.Instance;                      //  4 - Singleton

    if (singletonSqlClientFactory.Equals(dbProviderFactory))
    {
        Console.WriteLine("Provider SQL");
    }

    var connectionStringBuilder = dbProviderFactory.CreateConnectionStringBuilder();//  5 - Builder
    connectionStringBuilder.ConnectionString =                                      //  5 - Builder
        "Data Source=ServerName;Initial Catalog=DatabaseName;Persist Security " +
        "Info=True;Connection Timeout =60;Integrated Security=SSPI";

    dbConnection.ConnectionString = connectionStringBuilder.ConnectionString;

    var dbCommand = dbProviderFactory.CreateCommand();                       // 6 - Factory Method
    dbCommand.CommandType = CommandType.Text;
    dbCommand.CommandText = "select count(*) from Table1";
    dbCommand.Connection = dbConnection;

    if (dbCommand is ICloneable)
    {
        var prototypeDbCommand = (ICloneable)dbCommand;                       // 7 - Prototype
        var dbCommand2 = (DbCommand)prototypeDbCommand.Clone();               // 7 - Prototype
        dbCommand2.CommandText = "select count(*) from Table2";
    }

    try
    {
        dbConnection.Open();
        return dbCommand.ExecuteNonQuery();
    }
    finally
    {
        if (dbConnection.State != System.Data.ConnectionState.Closed)
            dbConnection.Close();
    }
    return -1;        
}

Diagramme UML des classes :

image

  • Abstract Factory : System.Data.Common.DbProviderFactory
Abstraction Fabrique concrète Classe abstraite à créer(famille de produits) Classe concrète à créer(famille de produits) Commentaires
DbProviderFactory SqlClientFactoryOdbcFactory DbCommandDbConnection OdbcCommand
SqlCommand
OdbcConnection
SqlConnection
Le pattern utilise un singleton pour ne disposer que d’une seule instance des fabriques concrètes pour l’ensemble des clients l’utilisant.Les méthodes CreateXXX sont des Factory Method chargées de créer chacune des familles de produits
  • Factory Method  : System.Data.Common.DbProviderFactories

Dans ce cas la factory method ne respecte pas le pattern avec son abstraction comme nous pourrons le voir dans la classe System.Net.WebRequest, mais grâce au paramètre passé à cette méthode (par réflexion) elle renverra l’instance du singleton d’une des fabriques concrète : SqlClientFactory ou OdbcFactory

  • Singleton  : System.Data.SqlClient.SqlClientFactory.Instance

Les instances uniques de chacune des factory sont créées ici par le constructeur statique de la classe en temps qu’instance de classe : OdbcFactory.Instance et SqlClientFactory.Instance

  • Builder  : System.Data.Common.DBConnectionStringBuilder
Abstraction Monteur concret Classe à monter
DBConnectionStringBuilder SqlConnectionStringBuilder
OdbcConnectionStringBuilder
StringString
  • Prototype  : System.ICloneable
Abstraction Classe à instance unique
ICloneable SqlCommand
OdbcCommand
SqlConnection
OdbcConnction
  • Autre exemples :

Voici d’autres exemples de ces patterns de création dans le framework :

public void WebRequestPatterns()
{
    var uriBuilder = new UriBuilder();                //  8 - Builder
    uriBuilder.Scheme = "http";
    uriBuilder.Host = "www.google.fr";

    var webRequest = WebRequest.Create(uriBuilder.Uri);  // 9 - Factory Method

    var webResponse = webRequest.GetResponse();          // 10 - Factory Method
}
public void XmlPatterns()
{
    var xmlDocument = new XmlDocument();
    xmlDocument.Load("file.xml");
    var xmlNode = xmlDocument.CloneNode(true);          // 11 - Prototype
}

Diagramme UML du pattern Factory Method de WebRequest

image

, , , , , , ,

Poster un commentaire