// Chaque client à son propre "main"
        public void Thread()
        {
            //on demande au client de s'authentifier
            sw.WriteLine("NICK!");
            sw.Flush();
            string nickString = null;
            try
            {
                nickString = sr.ReadLine();
            } catch(Exception e)
            {
                Fermerconnexion();
                return;
            }
            string[] commande = null;

            //on décortique la commande
            commande = GetCommande(nickString);

            //Le protocole dit : on doit envoyer NICK!LeNick - si ce n'est pas le cas on envoie le message d'erreur conséquent
            if (!commande[0].Equals("NICK") || commande[1] == null )
            {
                //le client n'a pas fourni son nom
                if (commande[1] == null)
                {
                    commande[1] = "Mauvaise authentification: NICK!Authentifiant attendu";

                }

                //on se garde une trace sur la console serveur
                Console.WriteLine(commande[1]);

                //on envoie l'erreur au client
                Erreur(commande[1]);

                // on ferme la connexion
                Fermerconnexion();

                // on sort de la méthode - tuer le thread.
                return;
            }

            if (!Regex.IsMatch(commande[1], @"^[a-zA-Z0-9_]+$"))
            {
                //on se garde une trace sur la console serveur
                Console.WriteLine(commande[1] + " ne contient pas uniquement des caractère alphanumérique et des soulignés");

                //on envoie l'erreur au client
                Erreur("votre nom contient des caractère proscrit : uniquement A-Z a-z 0-9 _ sont authorisés");

                // on ferme la connexion
                Fermerconnexion();

                // on sort de la méthode - tuer le thread.
                return;
            }

            //Si le nom est déjà dans la liste, erreur
            foreach (Client client in listeClient)
            {
                if (client.nick.ToUpper().Equals(commande[1].ToUpper()))
                {
                    Erreur("Ce nom est déjà présent");
                    Fermerconnexion();
                    return;
                }
            }

            //enregistrer le nom dans l'objet du client.
            this.nick = commande[1];

            //on se garde une trace
            Console.WriteLine(this.nick + " vient de se connecter");

            //on ajoute le client à la liste
            AjouterClient(this);

            //on repond au client avec HELO!.
            Ecrire("HELO!" + nick);

            //On doit diffuser que le client vient de se connecter
            DiffuserCommande(this, "JOIN");

            //tant que le client est actif (l'état va changer avec la commande QUIT!)
            bool active = true;

            //tant que le socket est connecté.
            while (ClientConnecte() && active)
            {

                //bloquant - jusqu'à ce qu'une ligne arrive ou encore une déconnexion violente
                string message = null;
                    try{
                       message = sr.ReadLine();
                    }
                catch (Exception e)
                    {
                        Console.WriteLine("message null, on déconnecte ce socket : "+e.Message);
                }

                //lorsque le socket se fait débrancher, sr.ReadLine() va débloquer et message va être à null
                if (message == null)
                {
                    //on se garde une trace dans la console pour indiquer que le client vient de se déconnecter.
                    Console.WriteLine(this.nick + " vient de se déconnecter");
                    // on demande à etre retirer de la liste;
                    RetirerClient(this);

                    //On doit diffuser que le client vient de se déconnecter.
                    Diffuser(this, "QUIT", "Socket terminé");

                    //on ferme les tream
                    Fermerconnexion();
                    //on sors de la méthode ce qui va tuer le thread. fermeture propre.
                    return;
                }

                Console.WriteLine(" message explicite >> " + message);
                //maintenant que les erreurs de deconnexions ont été géré.
                //on décortique la commande recu.
                commande = GetCommande(message);

                switch (commande[0])
                {
                    //message d'erreur
                    case "MSGE":
                        {
                            Erreur(commande[1]);
                            break;
                        }

                    //message à tous
                    case "MSGA":
                        {
                            if (commande[1] != null)
                            {
                                Diffuser(this, "MSGA", commande[1]);
                            }
                            else
                            {
                                Erreur("Le message ne peut pas être vide");
                            }
                            break;
                        }

                    //message privé
                    case "MSGP":
                        {

                            commande[1] = (commande[1] == null) ? "" : commande[1];

                            string[] destinataireMessage = AnalyseSousCommande(commande[1]);

                            if (destinataireMessage[0].Length == 0)
                            {
                                Erreur("Aucun destinataire spéficié");
                            }
                            else if (destinataireMessage[1].Length == 0)
                            {
                                Erreur("Aucun message spécifié");
                            }
                            else
                            {
                                Console.WriteLine("Tentative de message privé à envoyer à: " + destinataireMessage[0]);
                                bool envoye = false;

                                foreach (Client client in listeClient)
                                {
                                    if (client.nick.ToUpper().Equals(destinataireMessage[0].ToUpper()))
                                    {
                                        Ecrire("SUCC!" + commande[0]);
                                        client.Ecrire(commande[0] + "!" + this.nick + "!" + destinataireMessage[1]);
                                        envoye = true;
                                    }
                                }

                                if (!envoye)
                                {
                                    this.Erreur("aucun destinataire trouvé");
                                }

                            }
                            break;
                        }
                    /*
                     * Le protocol dit que le serveur doit répondre avec
                     * LIST!nom1,nom2,nom3,nom4.....nomN
                     * vous devez implémenter cette méthode
                     * */

                    case "LIST":
                        {

                            StringBuilder sb = new StringBuilder();
                            sb.Append("LIST!");
                            bool append = false;
                            foreach (Client client in listeClient)
                            {

                                sb.Append(client.nick + ",");
                                append = true;
                            }
                            //enleve la dernière virgule;
                            if (append)
                            {
                                sb.Length -= 1;
                            }
                            Ecrire(sb.ToString());
                            break;
                        }
                    case "QUIT":
                        {
                            Ecrire("SUCC!" + commande[0]);
                            if (commande[1] == null)
                            {
                                Diffuser(this, commande[0], "bye bye !");
                            }
                            else
                            {
                                Diffuser(this, commande[0], commande[1]);
                            }

                            active = false;
                            break;
                        }
                    case "CONN":
                        {
                            if (naoTts == null || naoMotion == null || naoPosture == null)
                            {
                                Console.WriteLine("Connection à NAO");

                                //naoTts = new TextToSpeechProxy("192.168.2.134", 9559);
                                naoTts = new TextToSpeechProxy("127.0.0.1", 9559);
                                Console.WriteLine("TextToSpeechProxy connecté");
                                naoTts.setLanguage("FRENCH");
                                naoTts.setVolume(0.3f);

                                //naoMotion = new MotionProxy("192.168.2.134", 9559);
                                naoMotion = new MotionProxy("127.0.0.1", 9559);
                                Console.WriteLine("MotionProxy connecté");

                                //naoPosture = new RobotPostureProxy("192.168.2.134", 9559);
                                naoPosture = new RobotPostureProxy("127.0.0.1", 9559);
                                Console.WriteLine("RobotPostureProxy connecté");

                                Console.WriteLine("CONN terminé");
                            }
                            else Console.WriteLine("Déjà connecté");
                            break;
                        }
                    case "INIT":
                        {
                            if (naoTts != null && naoMotion != null && naoPosture != null)
                            {
                                naoMotion.setStiffnesses("Body", 1f);
                                if (naoPosture.goToPosture("StandZero", 1f))
                                    naoTts.say("Initialisation terminée");
                                Console.WriteLine("Initialisation terminée");
                            }
                            else Console.WriteLine("CONN nécessaire avant INIT");
                            break;

                        }
                    case "TALK":
                        {
                            if (commande.Length > 1)
                            {
                                naoTts.say(commande[1]);
                                Console.WriteLine("NAO TextToSpeechProxy : {0}", commande[1]);
                            }
                            break;
                        }
                    case "STIF":
                        {
                            if(commande.Length > 1)
                            {
                                try
                                {
                                    naoMotion.setStiffnesses("Body", float.Parse(commande[1]));
                                }
                                catch(Exception e)
                                {
                                    Diffuser(this, "MSGA", "La commande STIF requiert un parametre valide");
                                }
                            }
                            else
                            {
                                Diffuser(this, "MSGA", "La commande STIF requiert un parametre");
                            }
                            break;
                        }
                    case "POST":
                        {
                            if(commande.Length == 2)
                            {
                                try
                                {
                                    naoPosture.goToPosture(commande[1], 1f);

                                }
                                catch(Exception)
                                {
                                    Diffuser(this, "MSGA", "Argument du POST invalide");
                                }
                            }
                            else
                            {
                                Diffuser(this, "MSGA", "POST requiert un argument");
                            }

                            break;
                        }
                    case "MOVE":
                        {
                            if(commande[1] != null)
                            {
                                string[] args = commande[1].Split('!');

                                args = args.Select(x => x.Replace(".", ",")).ToArray();

                                if(args.Length > 1)
                                {
                                    string joint = args[0];
                                    float angle = 0;
                                    float.TryParse(args[1], out angle);
                                    float vitesse = 0.1f;

                                    try
                                    {
                                        naoMotion.setAngles(joint, angle, vitesse);
                                    }
                                    catch(Exception e)
                                    {
                                        Console.WriteLine(e);
                                    }
                                }
                            }
                            break;
                        }
                    case "TEST":
                        {
                            if (commande.Length > 1)
                            {
                                string[] args = commande[1].Split('!');

                                args = args.Select(x => x.Replace(".", ",")).ToArray();

                                    if (args.Length > 6)
                                    {
                                        string chainName = args[0];
                                        int space = 0;
                                        float[] position = {
                                                       float.Parse(args[1]),
                                                       float.Parse(args[2]),
                                                       float.Parse(args[3]),
                                                       float.Parse(args[4]),
                                                       float.Parse(args[5]),
                                                       float.Parse(args[6]),
                                                   };
                                        int axisMask = 63;

                                        naoMotion.setPosition(chainName, space, position.ToList<float>(), 0.4f, axisMask);
                                    }
                            }
                            break;
                        }
                    case "RGHT":
                        {
                            if (commande.Length > 1)
                            {
                                string[] args = commande[1].Split('!');

                                args = args.Select(x => x.Replace(".", ",")).ToArray();

                                if (args.Length > 2)
                                {
                                    float[] position = {
                                                       float.Parse(args[0]),
                                                       float.Parse(args[1]),
                                                       float.Parse(args[2]),
                                                        0f,
                                                        0f,
                                                        0f
                                                       };

                                    float[] currPosition = naoMotion.getPosition("RArm",0,true).ToArray();
                                    float[] deltaPosition = new float[6];

                                    for(int i = 0; i < 6; i++)
                                    {
                                        deltaPosition[i] = (position[i] - currPosition[i]) / 10;
                                    }

                                    Diffuser(this, "MSGA", message);
                                    naoMotion.changePosition("RArm", 0, position.ToList<float>(), 0.8f, 63);
                                }
                            }
                            break;
                        }
                    default:
                        {
                            Erreur("Commande non implémenté sur le serveur");
                            break;
                        }
                }
            }

            Console.WriteLine(this.nick + " vient de se deconnecter");

            // on se retire soi-même de la liste;
            RetirerClient(this);

            //on ferme les socket et les streams
            Fermerconnexion();

            //le thread va mourrir... sniff sniff
        }
        static void Main(string[] args)
        {
            string mIp = "127.0.0.1";
            //string mIp = "192.168.1.134";
            int mPort = 9559;

            GamePadState state;
            state = GamePad.GetState(PlayerIndex.One);

            MotionProxy motion = new MotionProxy(mIp, mPort);
            Console.WriteLine("MotionProxy connecté à {0}:{1}", mIp, mPort);
            TextToSpeechProxy tts = new TextToSpeechProxy(mIp, mPort);
            Console.WriteLine("TextToSpeechProxy connecté à {0}:{1}", mIp, mPort);
            RobotPostureProxy posture = new RobotPostureProxy(mIp,mPort);
            Console.WriteLine("RobotPostureProxy connecté à {0}:{1}", mIp, mPort);

            tts.setLanguage("French");
            motion.setStiffnesses("Body", 1f);

            Console.WriteLine();

            Console.WriteLine("En attente de connection de la manette");

            while (!state.IsConnected)
            {
                state = GamePad.GetState(PlayerIndex.One);
            }

            Console.WriteLine("Manette connectée");

            Object[] headJoints = { "HeadYaw", "HeadPitch" };
            Object[] rshoulderJoints = { "RShoulderRoll", "RShoulderPitch" };
            Object[] lelbowJoints = { "LElbowYaw", "LElbowRoll" };
            Object[] handsJoints = { "LHand", "RHand" };
            Object[] handAngles = new Object[2];
            Object[] Angles = new Object[2];

            float horizontal = 0f;
            float parallel = 0f;
            float theta = 0f;
            float percentMaxSpeed = 0.5f;

            while (state.IsConnected && state.Buttons.Back == ButtonState.Released )
            {
                state = GamePad.GetState(PlayerIndex.One);

                if (state.Buttons.A == ButtonState.Pressed)
                {
                    tts.setLanguage("French");
                    tts.say("Bonjour");
                }

                if(state.Buttons.B == ButtonState.Pressed)
                {
                    tts.setLanguage("English");
                    tts.say("Hello");
                }

                if (state.Buttons.X == ButtonState.Pressed) posture.goToPosture("Crouch", 1f) ;
                if (state.Buttons.Y == ButtonState.Pressed) posture.goToPosture("Stand", 1f);
                if (state.Buttons.Start == ButtonState.Pressed) posture.goToPosture("StandZero", 1f);
                if (state.DPad.Up == ButtonState.Pressed) posture.goToPosture("LyingBelly", 1f);
                if (state.DPad.Down == ButtonState.Pressed) posture.goToPosture("LyingBack", 1f);
                if (state.DPad.Left == ButtonState.Pressed) posture.goToPosture("SitRelax", 1f);
                if (state.DPad.Right == ButtonState.Pressed) posture.goToPosture("Sit", 1f);

                float modX = 1.75f;
                float modY = 2f;
                Angles = new Object[] { -state.ThumbSticks.Right.X * modX, -state.ThumbSticks.Right.Y * modY };

                if (state.ThumbSticks.Left.Y <= -0.1f || state.ThumbSticks.Left.Y >= 0.1f)
                    horizontal = state.ThumbSticks.Left.Y;
                else horizontal = 0f;

                if (state.ThumbSticks.Left.X <= -0.1f || state.ThumbSticks.Left.X >= 0.1f)
                    theta = -state.ThumbSticks.Left.X;
                else theta = 0f;

                if (state.Triggers.Left >= 0.1f)
                    parallel = state.Triggers.Left;
                else if (state.Buttons.LeftShoulder == ButtonState.Pressed)
                    parallel = -state.Triggers.Right;
                else parallel = 0f;

                handAngles = new Object[] {
                    state.Buttons.LeftShoulder == ButtonState.Pressed ? 0f : 1f,
                    state.Buttons.RightShoulder == ButtonState.Pressed ? 0f : 1f
                };

                motion.move(horizontal, parallel, theta);

                //motion.setAngles(rshoulderJoints, Angles, percentMaxSpeed);
                motion.setAngles(headJoints, Angles, percentMaxSpeed);
                //motion.setAngles(lelbowJoints, Angles, percentMaxSpeed);
                motion.setAngles(handsJoints, handAngles, 1f);

            }
        }