private static IncomingToken ByName(string name)
        {
            IncomingToken token = null;

            if (_tokenDict.TryGetValue(name, out token))
            {
                return(token);
            }
            return(null);
        }
        public static bool MatchAndExecuteToken(string name)
        {
            IncomingToken token = ByName(name);

            if (token == null)
            {
                return(false);
            }
            else
            {
                token._bindingFunc.Invoke();
                return(true);
            }
        }
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication    uiApp  = commandData.Application;
            Document         doc    = uiApp.ActiveUIDocument.Document;
            Selection        sel    = uiApp.ActiveUIDocument.Selection;
            List <Reference> picked = sel.PickObjects(ObjectType.Element, "Select the objects that you want to group").ToList();

            List <List <string> > words = new List <List <string> >();

            foreach (var objRef in picked)
            {
                Element       elem = doc.GetElement(objRef);
                string        className;
                List <string> elemWords = new List <string>();
                if (_ifcNameMap.TryGetValue(elem.Category.Name, out className) && !elemWords.Contains(className))
                {
                    elemWords.Add(className);
                }
                List <ElementId> matIds = elem.GetMaterialIds(true).ToList();
                matIds.AddRange(elem.GetMaterialIds(false).ToList());
                foreach (var id in matIds)
                {
                    string word = ProcessString(doc.GetElement(id).Name);
                    if (word == "")
                    {
                        continue;
                    }
                    if (!elemWords.Contains(word))
                    {
                        elemWords.Add(word);
                    }
                }

                words.Add(elemWords);
            }

            string msg = String.Join("\n", words.Select((l) => String.Join(" ", l.ToArray())).ToArray());

            RevitClient.SendData(msg);
            string response = RevitClient.ListenAndReturnData();

            if (IncomingToken.MatchAndExecuteToken(response))
            {
                return(Result.Succeeded);
            }

            TaskDialog box = new TaskDialog("Python Server");

            box.MainInstruction = "Odd one out: ";
            box.MainContent     = response;
            box.Show();
            //RevitClient.SendData(msg);
            //ask user to select a bunch of items
            //get their material names, and ifc names
            //serialize the data into a string
            //send the data
            //receive the inference back from the server
            //deserialize the received inference appropriately
            //display a message window to show the user that inference.
            //incomplete
            return(Result.Succeeded);
        }