private Utterance UtteranceFromHistoryItem(UtteranceHistoryItem uhi)                          
 {
     RepetitionType repetition = default(RepetitionType);
     var result = Enum.TryParse<RepetitionType>(uhi.repetitions,true,out repetition);
     if (!result)
     {
         Console.WriteLine("WARNING! Couldn't parse correctly UtteranceHistoryItem repetition field! Value =  "+uhi.repetitions);
     }
     var u = new Utterance(uhi.utteranceId,uhi.library,uhi.utterance,uhi.category,uhi.subcategory,uhi.question,repetition);
     return u;
 }
 public void AddToHistory(string utteranceThalamusId, Utterance u)
 {
     if (!_recentHistory.Contains(u)) _recentHistory.Add(u);
     if (!_totalHistory.Contains(u))
     {
         using (TextWriter writer = new StreamWriter(_totalHistoryFilePath, true))
         {
             writer.WriteLine(u.Id + "," + u.Library + "," + u.Text + "," + u.Category + "," + u.Subcategory + ","+u.IsQuestion+","+u.Repetitions);
         }
         _totalHistory.Add(u);
     }
 }
예제 #3
0
 private void NotifyUtteranceState(UtteranceStates state, Utterance utt = null)
 {
     if (UtteranceState != null) UtteranceState(state, utt);
 }
예제 #4
0
 private void ExecuteUtterance(Utterance utterance)
 {
     if (utterance == null || utterance.Text == null || utterance.Text.Trim() == "") {
         performingUtterance = new Utterance();
         SkPublisher.UtteranceStarted(utterance.ThalamusId);
         SkPublisher.UtteranceFinished(utterance.ThalamusId);
         performingUtterance = null;
     }else
     {
         backchanneledCurrentQuestion = false;
         backchannellingCurrentQuestion = false;
         utteranceFinishedTimeoutClock.Restart();
         performingUtterance = utterance;
         NotifyUtteranceState(UtteranceStates.Performing, utterance);
         if (utterance.IsQuestion) SkPublisher.UtteranceIsAQuestion(utterance.ThalamusId);
         SkPublisher.SpeakBookmarks(utterance.ThalamusId, utterance.TextArray, utterance.BookmarkArray);
         
     //Utterances.HistoryManager.HistoryManagerFactory.GetHistoryManager().AddToHistory(utterance.ThalamusId, utterance);     // This works here, but it's not good practice to have it here. Move this code in a better place when refactoring the class
     }
 }
예제 #5
0
        public string PerformUtterance(string id, Utterance utterance, bool execute = true)
        {
            if (utterance == null || utterance.Text == null || utterance.Text.Trim() == "")
            {
                lock (utterancesQueue)
                {
                    Utterance u = new Utterance("");
                    u.ThalamusId = id;
                    utterancesQueue.Enqueue(u);
                    Debug("Queued Empty Utterance");
                }
                return "";
            }

            if (stripSlashes)
            {
                utterance.Text = utterance.Text.Replace('/', ' ');
            }

            string fmlSpeech = utterance.Text;
            if (UseRelativeSpeed) fmlSpeech = String.Format("\\rspd={0}\\ {1}", relativeSpeed.ToString(), fmlSpeech);

            if (id == "") id = Guid.NewGuid().ToString();
            utterance.ThalamusId = id;
            targetsUtterances[id] = new List<string>();
            Regex re = new Regex(@"(?<=>)|(?=<)");
            string[] parts = re.Split(fmlSpeech);
            bool textStarted = false;
            List<String> text = new List<string>();
            List<String> bookmarks = new List<string>();
            string currentBookmark = String.Format("{0:X8}BM_{1}", fmlSpeech.GetHashCode(), 0); ;
            int bookmarkCount = 1;
			int animateCount = 0;
            int headCount = 0;
            int faceCount = 0;
            Action toAddGaze = null;
            Action toAddNonGaze = null;
            bool useNonGaze = false;
            int i = 0;
            List<Action> actions = new List<Action>();

            #region Tags replacement and filling
            foreach (string p in parts)
            {
                i++;
                string block = p.Trim();
                if (block.Length == 0) continue;
                if (block.StartsWith("<") && block.EndsWith(">"))
                {
                    int start = block.IndexOf("(") + 1;
                    string correctParam = block.Substring(start, block.LastIndexOf(")") - start);
                    string param = correctParam.ToLower();
                    block = block.ToUpper().Trim();

                    if (block.StartsWith("<GAZEANDPOINTANDHIGHLIGHT")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            toAddGaze = () => Targets[param].Generate(this, TargetType.Gaze);
                            toAddNonGaze = () => Targets[param].Generate(this, TargetType.Gaze, true);
                            actions.Add((() => Targets[param].Generate(this, TargetType.Pointing)));
                            actions.Add((() => Targets[param].Generate(this, TargetType.Highlight)));
                            Debug("Queued <{0}({1})>", "GAZE", param);
                            Debug("Queued <{0}({1})>", "POINT", param);
                            Debug("Queued <{0}({1})>", "HIGHLIGHT", param);
                        }
                    }
                    else if (block.StartsWith("<GLANCEANDPOINTANDHIGHLIGHT")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            if (toAddGaze != null) useNonGaze = true;
                            toAddGaze = () => Targets[param].Generate(this, TargetType.Glance);
                            actions.Add((() => Targets[param].Generate(this, TargetType.Pointing)));
                            actions.Add((() => Targets[param].Generate(this, TargetType.Highlight)));
                            Debug("Queued <{0}({1})>", "GLANCE", param);
                            Debug("Queued <{0}({1})>", "POINT", param);
                            Debug("Queued <{0}({1})>", "HIGHLIGHT", param);
                        }
                    }
                    else if (block.StartsWith("<GLANCEANDWAVEANDHIGHLIGHT")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            if (toAddGaze != null) useNonGaze = true;
                            toAddGaze = () => Targets[param].Generate(this, TargetType.Glance);
                            actions.Add((() => Targets[param].Generate(this, TargetType.Waving)));
                            actions.Add((() => Targets[param].Generate(this, TargetType.Highlight)));
                            Debug("Queued <{0}({1})>", "GLANCE", param);
                            Debug("Queued <{0}({1})>", "WAVE", param);
                            Debug("Queued <{0}({1})>", "HIGHLIGHT", param);
                        }
                    }
                    else if (block.StartsWith("<GAZEANDPOINT")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            toAddGaze = () => Targets[param].Generate(this, TargetType.Gaze);
                            toAddNonGaze = () => Targets[param].Generate(this, TargetType.Gaze, true);
                            actions.Add((() => Targets[param].Generate(this, TargetType.Pointing)));
                            Debug("Queued <{0}({1})>", "GAZE", param);
                            Debug("Queued <{0}({1})>", "POINT", param);
                        }
                    }
                    else if (block.StartsWith("<GAZEANDWAVE")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            toAddGaze = () => Targets[param].Generate(this, TargetType.Gaze);
                            toAddNonGaze = () => Targets[param].Generate(this, TargetType.Gaze, true);
                            actions.Add((() => Targets[param].Generate(this, TargetType.Waving)));
                            Debug("Queued <{0}({1})>", "GAZE", param);
                            Debug("Queued <{0}({1})>", "WAVE", param);
                        }
                    }
                    else if (block.StartsWith("<GAZEANDHIGHLIGHT")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            toAddGaze = () => Targets[param].Generate(this, TargetType.Gaze);
                            toAddNonGaze = () => Targets[param].Generate(this, TargetType.Gaze, true);
                            actions.Add((() => Targets[param].Generate(this, TargetType.Highlight)));
                            Debug("Queued <{0}({1})>", "GAZE", param);
                            Debug("Queued <{0}({1})>", "HIGHLIGHT", param);
                        }
                    }
                    else if (block.StartsWith("<GLANCEANDPOINT")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            if (toAddGaze != null) useNonGaze = true;
                            toAddGaze = () => Targets[param].Generate(this, TargetType.Glance);
                            actions.Add((() => Targets[param].Generate(this, TargetType.Pointing)));
                            Debug("Queued <{0}({1})>", "GLANCE", param);
                            Debug("Queued <{0}({1})>", "POINT", param);
                        }
                    }
                    else if (block.StartsWith("<GLANCEANDWAVE")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            if (toAddGaze != null) useNonGaze = true;
                            toAddGaze = () => Targets[param].Generate(this, TargetType.Glance);
                            actions.Add((() => Targets[param].Generate(this, TargetType.Waving)));
                            Debug("Queued <{0}({1})>", "GLANCE", param);
                            Debug("Queued <{0}({1})>", "WAVE", param);
                        }
                    }
                    else if (block.StartsWith("<GLANCEANDHIGHLIGHT")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            if (toAddGaze != null) useNonGaze = true;
                            toAddGaze = () => Targets[param].Generate(this, TargetType.Glance);
                            actions.Add((() => Targets[param].Generate(this, TargetType.Highlight)));
                            Debug("Queued <{0}({1})>", "GLANCE", param);
                            Debug("Queued <{0}({1})>", "HIGHLIGHT", param);
                        }
                    }
                    else if (block.StartsWith("<POINTANDHIGHLIGHT")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            actions.Add((() => Targets[param].Generate(this, TargetType.Waving)));
                            actions.Add((() => Targets[param].Generate(this, TargetType.Highlight)));
                            Debug("Queued <{0}({1})>", "WAVE", param);
                            Debug("Queued <{0}({1})>", "HIGHLIGHT", param);
                        }
                    }
                    else if (block.StartsWith("<WAVEANDHIGHLIGHT")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            actions.Add((() => Targets[param].Generate(this, TargetType.Pointing)));
                            actions.Add((() => Targets[param].Generate(this, TargetType.Highlight)));
                            Debug("Queued <{0}({1})>", "POINT", param);
                            Debug("Queued <{0}({1})>", "HIGHLIGHT", param);
                        }
                    }
                    else if (block.StartsWith("<GAZE")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            toAddGaze = () => Targets[param].Generate(this, TargetType.Gaze);
                            toAddNonGaze = () => Targets[param].Generate(this, TargetType.Gaze, true);
                            Debug("Queued <{0}({1})>", "GAZE", param);
                        }
                    }
                    else if (block.StartsWith("<GLANCE")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            if (toAddGaze != null) useNonGaze = true;
                            toAddGaze = () => Targets[param].Generate(this, TargetType.Glance);
                            Debug("Queued <{0}({1})>", "GLANCE", param);
                        }
                    }
                    else if (block.StartsWith("<POINT")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            actions.Add((() => Targets[param].Generate(this, TargetType.Pointing)));
                            Debug("Queued <{0}({1})>", "POINT", param);
                        }
                    }
                    else if (block.StartsWith("<WAVE")) //param = target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            actions.Add((() => Targets[param].Generate(this, TargetType.Waving)));
                            Debug("Queued <{0}({1})>", "WAVE", param);
                        }
                    }
                    else if (block.StartsWith("<ANIMATE")) //param = animationName
                    {
                        correctParam.Replace(" ", string.Empty);
                        actions.Add((() => SkPublisher.PlayAnimation(String.Format("{0:X8}ANIMATE_{1}", fmlSpeech.GetHashCode(), animateCount++), correctParam)));
                        Debug("Queued <{0}({1})>", "ANIMATE", correctParam);
                    }
                    else if (block.StartsWith("<HEADNODNEGATIVE")) //param = count
                    {
                        int count = 2;
                        if (param.Length > 0) try { count = int.Parse(param, ifp); }
                            catch { }
                        actions.Add((() => SkPublisher.Head(String.Format("{0:X8}HEAD_{1}", fmlSpeech.GetHashCode(), headCount++), "SHAKE", count, 10, 2)));
                        Debug("Queued <{0}({1})>", "HEADNODNEGATIVE", param);
                    }
                    else if (block.StartsWith("<HEADNOD")) //param = count
                    {
                        int count = 2;
                        if (param.Length > 0) try { count = int.Parse(param, ifp); }
                            catch { }
                        actions.Add((() => SkPublisher.Head(String.Format("{0:X8}HEAD_{1}", fmlSpeech.GetHashCode(), headCount++), "NOD", count, 10, 2)));
                        Debug("Queued <{0}({1})>", "HEADNOD", param);
                    }
                    else if (block.StartsWith("<FACE")) //param = lexeme
                    {
                        toAddGaze = () => SkPublisher.FaceLexeme(String.Format("{0:X8}FACE_{1}", fmlSpeech.GetHashCode(), faceCount++), param); ;
                        Debug("Queued <{0}({1})>", "FACE", param);
                    }
                    else if (block.StartsWith("<FACESHIFT")) //param = lexeme
                    {
                        toAddGaze = () => SkPublisher.FaceShiftLexeme(String.Format("{0:X8}FACESHIFT_{1}", fmlSpeech.GetHashCode(), faceCount++), param); ;
                        Debug("Queued <{0}({1})>", "FACESHIFT", param);
                    }
                    else if (block.StartsWith("<EYEBLINK")) //param = count
                    {
                        int count = 1;
                        if (param.Length > 0) try { count = int.Parse(param, ifp); }
                            catch { }
                        toAddGaze = () => SkPublisher.EyeBlink(count); ;
                        Debug("Queued <{0}({1})>", "EYEBLINK", count);
                    }
                    else if (block.StartsWith("<SLOWEYEBLINK")) //param = count
                    {
                        int count = 1;
                        if (param.Length > 0) try { count = int.Parse(param, ifp); }
                            catch { }
                        toAddGaze = () => SkPublisher.SlowEyeBlink(count); ;
                        Debug("Queued <{0}({1})>", "SLOWEYEBLINK", count);
                    }
                    else if (block.StartsWith("<GAME")) //param = game action
                    {
                        Debug("Queued <{0}({1})>", "GAME", correctParam);
                        string actionName = correctParam.Substring(0, correctParam.IndexOf(',') == -1 ? correctParam.Length : correctParam.IndexOf(','));
                        string actionParam = "";
                        if (correctParam.IndexOf(',') != -1) actionParam = correctParam.Substring(correctParam.IndexOf(',') + 1, correctParam.Length - correctParam.IndexOf(',') - 1);
                        actions.Add((() => SkPublisher.RunAction(actionName, actionParam)));
                    }
                    else if (block.StartsWith("<HIGHLIGHT")) //param = screen target
                    {
                        if (Targets.ContainsKey(param))
                        {
                            actions.Add((() => Targets[param].Generate(this, TargetType.Highlight)));
                            Debug("Queued <{0}({1})>", "HIGHLIGHT", param);
                        }
                    }
                    else
                    {
                        DebugError("Invalid instruction '{0}' in utterance '{1}'!", block, text);
                        return "";
                    }

                    if (execute)
                    {
                        //depois de cada tag
                        if (textStarted)
                        {
                            Debug("bookmark: " + currentBookmark + " block: " + block);
                            foreach (Action a in actions)
                            {
                                QueueTarget(currentBookmark, a, id);
                            }
                        }
                        else
                        {
                            foreach (Action a in actions) a();
                        }
                    }
                    actions.Clear();
                }
                else
                {
                    //just a text block
                    if (textStarted)
                    {
                        if (execute)
                        {
                            if (useNonGaze && toAddNonGaze != null) QueueTarget(currentBookmark, toAddNonGaze, id);
                            if (toAddGaze != null) QueueTarget(currentBookmark, toAddGaze, id);
                        }
                        if (i < parts.Length)
                        {
                            bookmarks.Add(currentBookmark);
                            currentBookmark = String.Format("{0:X8}BM_{1}", fmlSpeech.GetHashCode(), bookmarkCount++);
                        }
                        
                    }
                    else
                    {
                        if (execute)
                        {
                            if (useNonGaze && toAddNonGaze != null) toAddNonGaze();
                            if (toAddGaze != null) toAddGaze();
                        }
                    }
                    useNonGaze = false;
                    toAddGaze = null;
                    toAddNonGaze = null;
                    
                    //break the block into sequences of 3 words and keep a random bookmark inbetween them so that we have a constant status on the text being spoken.
                    string[] blockSplit = block.Split(' ');
                    //block = "";
                    for (int j = 0; j < blockSplit.Length; j++)
                    {
                        block = blockSplit[j] + " ";
                        for (int m = 1; m < bookmarkWordInterval && j+m<blockSplit.Length; m++)
                        {
                            block += blockSplit[j+m] + " ";
                        }
                        j += bookmarkWordInterval-1;
                        text.Add(block);
                        
                        currentBookmark = String.Format("{0:X8}BM_{1}", fmlSpeech.GetHashCode(), bookmarkCount++);
                        bookmarks.Add(currentBookmark);
                    }

                    //text.Add(block);
                    textStarted = true;
                }
            }
#endregion

            if (execute)
            {
                if (textStarted)
                {
                    if (useNonGaze && toAddNonGaze != null) QueueTarget(currentBookmark, toAddNonGaze, id);
                    if (toAddGaze != null) QueueTarget(currentBookmark, toAddGaze, id);
                }
                else
                {
                    if (useNonGaze && toAddNonGaze != null) toAddNonGaze();
                    if (toAddGaze != null) toAddGaze();
                }
                bookmarks.Add(currentBookmark);

                //if (a_text.Length>0) a_text[a_text.Length-1]+="  \\rst\\";
                utterance.SetTextBookmarks(text.ToArray(), bookmarks.ToArray());

                lock (utterancesQueue)
                {
                    utterancesQueue.Enqueue(utterance);
                    Utterances.HistoryManager.HistoryManagerFactory.GetHistoryManager().AddToHistory(utterance.ThalamusId, utterance);
                    Debug("Queued Utterance");
                }

                /*if (currentlyActiveSpeaker == ActiveUser.None)
                {
                    Debug("My turn to speak.");
                    
                }
                else
                {
                    Debug("Being polite...");
                    politeUtterance = utterance;
                }*/
            }
            return id;
        }
예제 #6
0
 public string PerformUtterance(string id, Utterance utterance, string[] tagNames, string[] tagValues, bool execute = true)
 {
     for (int i = 0; i < tagNames.Length; i++)
     {
         if (tagNames[i].Length > 0)
             utterance.Text = utterance.Text.Replace(tagNames[i], tagValues[i]);
     }
     return PerformUtterance(id, utterance);
 }
예제 #7
0
 public bool VerifyUtterance(Utterance utterance)
 {
     try
     {
         return PerformUtterance("", utterance, false) != "";
     }
     catch
     {
         return false;
     }
 }
예제 #8
0
 /// <summary>
 /// Check if an utterance can be use. If the utterance is marked as OnceAndForever or OnceInASession, it checks if it was or it wasn't used .
 /// </summary>
 /// <param name="utterance"></param>
 /// <returns>
 /// Returns true if the utterance is valid and can be used
 /// </returns>
 private static bool CheckHistory(Utterance utterance)
 {
     IUtterancesHistoryManager utterancesHistoryManager = HistoryManagerFactory.GetHistoryManager();
     return !(utterance.Repetitions == RepetitionType.OnceAndForever && utterancesHistoryManager.WasEverUsed(utterance)) &&
            !(utterance.Repetitions == RepetitionType.OnceInASession && utterancesHistoryManager.WasRecentlyUsed(utterance));
 }
예제 #9
0
 private void DelayedUtteranceFinished(object oid)
 {
     Stopwatch timer = new Stopwatch();
     timer.Start();
     Debug("Waiting for answer...");
     while (waitingForQuestionAnswer && timer.ElapsedMilliseconds < _questionsFinishEventDelaySeconds * 1000) Thread.Sleep(200);
     if (waitingForQuestionAnswer) Debug("Sick of waiting.");
     else Debug("Got answer.");
     string id = (string)oid;
     SkPublisher.UtteranceFinished(id);
     performingUtterance = null;
     waitingForQuestionAnswer = false;
     Debug("Finished Utterance");
 }
예제 #10
0
 private void DelayedNVBUtteranceFinished(object oid)
 {
     Stopwatch timer = new Stopwatch();
     timer.Start();
     Debug("Waiting for NVB...");
     while (timer.ElapsedMilliseconds < utterancesSafeDuration * 1000) Thread.Sleep(200);
     string id = (string)oid;
     SkPublisher.UtteranceFinished(id);
     performingUtterance = null;
     Debug("Finished Utterance");
 }
예제 #11
0
 private void FinishedUtterance(string id, bool immediately = false) 
 {
     lock(targetsUtterances) {
         lock(targetsQueue) {
             if (id!="") 
             {
                 if (targetsUtterances.ContainsKey(id))
                 {
                     foreach (string targetId in targetsUtterances[id])
                     {
                         if (targetsQueue.ContainsKey(targetId)) targetsQueue.Remove(targetId);
                     }
                     targetsUtterances.Remove(id);
                 }
             }
             else
             {
                 foreach(string utteranceId in targetsUtterances.Keys) {
                     foreach (string targetId in targetsUtterances[utteranceId])
                     {
                         if (targetsQueue.ContainsKey(targetId)) targetsQueue.Remove(targetId);
                     }
                 }
                 targetsUtterances.Clear();
             }
         }
     }
     // Delaying the utterance finished message in case the last utterance was a question
     // TODO: wait for one of the players to say something before sending the utterance finished event. In case no one is speaking, than use a timeout to send the event.
     if (!immediately && performingUtterance != null && performingUtterance.IsQuestion)
     {
         waitingForQuestionAnswer = true;
         NotifyUtteranceState(UtteranceStates.QuestionWaiting);
         (new Thread(new ParameterizedThreadStart(DelayedUtteranceFinished))).Start(id);
     }
     else if (performingUtterance != null && (performingUtterance.TextArray.Length == 0 || performingUtterance.TextArray[0].Trim() == ""))
     {
         NotifyUtteranceState(UtteranceStates.NVBWaiting);
         (new Thread(new ParameterizedThreadStart(DelayedNVBUtteranceFinished))).Start(id);
     }
     else
     {
         waitingForQuestionAnswer = false;
         SkPublisher.UtteranceFinished(id);
         performingUtterance = null;
         Debug("Finished Utterance");
     }
     
     
 }
 public bool WasEverUsed(Utterance u)
 {
     if (_totalHistory == null) return false;
     return _totalHistory.Contains(u);
 }
 public bool WasRecentlyUsed(Utterance u)
 {
     if (_recentHistory == null) return false;
     return _recentHistory.Contains(u);
 }
 public void AddToHistory(string utteranceThalamusId,Utterance u)
 {
     _client.SkPublisher.UtteranceUsed(u.Id, u.SerializeToJson());
     if (!_recentHistory.Contains(u)) _recentHistory.Add(u);
     if (!_totalHistory.Contains(u)) _totalHistory.Add(u);
 }
 public bool WasRecentlyUsed(Utterance u)
 {
     return _recentHistory.Contains(u);
 }
예제 #16
0
        public void PerformUtteranceFromLibrary(string id, string category, string subcategory, string[] tagNames, string[] tagValues)
        {
            utteranceLibraries.Keys.ToArray();
            if (tagNames.Length != tagValues.Length) DebugError("tagNames count differs from tagValues count! These arrays should have the same number of elements.");

            Utterance utterance = null;
            if (UseCompositeLibrary)
            {
                utterance = UtteranceLibrary.GetCompositeUtterance(utteranceLibraries.Values.ToList(), category, subcategory);
            }
            else
            {
                if (utteranceLibraries.ContainsKey(SelectedLibrary)) utterance = utteranceLibraries[SelectedLibrary].GetUtterance(category, subcategory);
            }
            if (utterance==null) utterance = new Utterance("");
            utterance.ThalamusId = id;
            for (int i = 0; i < tagNames.Length; i++)
            {
                if (tagNames[i].Length>0)
                    utterance.Text = utterance.Text.Replace(tagNames[i], tagValues[i]);
            }

            PerformUtterance(id, utterance);
        }
 public bool WasEverUsed(Utterance u)
 {
     return _totalHistory.Contains(u);
 }
예제 #18
0
 private List<Utterance> QueryUtterancesStartsWith(string fullCategory)
 {
     var filteredUtterances = new List<Utterance>();
     System.Data.EnumerableRowCollection temp;
     temp = Utterances.AsEnumerable().Where(row => row.Field<string>(FIELD_CATEGORY).ToLower().StartsWith(fullCategory));
     foreach (DataRow x in temp)
     {
         string id = x.Table.Columns.Contains(FIELD_ID) ? x[FIELD_ID].ToString() : "";
         string library = Path.GetFileName(libraryFilename);
         string text = x[FIELD_TEXT].ToString();
         string[] catSplit = x[FIELD_CATEGORY].ToString().Split(new char[] { ':' }, 2);
         string cat = catSplit[0];
         string sub = catSplit.Length > 1 ? catSplit[1] : "-";
         string memory = x.Table.Columns.Contains(FIELD_QUESTION) ? x[FIELD_QUESTION].ToString() : "";
         string repetitions = x.Table.Columns.Contains(FIELD_REPETITIONS) ? x[FIELD_REPETITIONS].ToString() : "";
         var ut = new Utterance(id, library, text, cat, sub, memory, repetitions);
         filteredUtterances.Add(ut);
     }
     return filteredUtterances;
 }