/// <summary> /// Given a seuqnece of phrases, generate suggestions about potential fragments that can together form a valid fragment group /// Or if it doesn't belong any fragment group (i.e. it's a standalone fragment), just return informaion about itself /// </summary> /// <param name="keyPhrases"></param> /// <param name="nextClues"></param> /// <param name="foundDocuments"></param> private void FindPotentialGroupFragments(string[] keyPhrases, out List <ClueFragment> nextClues, out List <Document> foundDocuments) { nextClues = null; foundDocuments = null; List <string> companionFragments = GetPotentialGroupFragments(keyPhrases); if (companionFragments != null) { // Generate return results nextClues = new List <ClueFragment>(); foreach (string fragment in companionFragments) { HashSet <Document> relatedDocuments = Fragments[fragment].Documents; nextClues.Add(new ClueFragment(fragment, relatedDocuments.Count, fragment, relatedDocuments.ToList())); } } else { if (keyPhrases.Length == 1 && Fragments.ContainsKey(keyPhrases[0])) { foundDocuments = Fragments[keyPhrases[0]].Documents.ToList(); } } }
/// <summary> /// Given a fragment, find whether or not it matches any existing fragments - either partial or completely; Return all matches /// Partial means anywhere, not just beginning characters; Return value can exclude exact match of partialFragment, if specifed /// </summary> /// <param name="partialFragment"></param> /// <param name="partialMatches"></param> /// <param name="bExcludeSearch"></param> /// <returns></returns> private bool TryGetFragmentFromPartialString(string partialFragment, out List <FragmentInfo> partialMatches, bool bExcludeSearch = false) { partialMatches = new List <FragmentInfo>(); if (Fragments.ContainsKey(partialFragment)) { partialMatches.Add(Fragments[partialFragment]); } else { foreach (KeyValuePair <string, FragmentInfo> entry in Fragments) { if (entry.Key.Contains(partialFragment) == true) { if (bExcludeSearch == true && partialFragment == entry.Key) { continue; } else { partialMatches.Add(entry.Value); } } } } if (partialMatches.Count != 0) { return(true); } else { partialMatches = null; return(false); } }
//#region Deprecated Dctionary<string, ClueNode> Clue(Tree) construct //public void AddDocumentToClue(string clue, Document doc) //{ // string[] clueFragments = SeperateClueFragments(clue); // if (Clues.ContainsKey(clueFragments[0]) == false) // Clues[clueFragments[0]] = new ClueNode(); // Clues[clueFragments[0]].AddDocument(clueFragments, 0, doc); //} //public List<Document> GetDocumentsFromClue(string clue) //{ // string[] clueFragments = SeperateClueFragments(clue); // return GetDocumentsFromPhrases(clueFragments); //} //public List<Document> GetDocumentsFromPhrases(string[] cluePhrases) //{ // if (Clues.ContainsKey(cluePhrases[0]) != false) // return Clues[cluePhrases[0]].GetDocuments(cluePhrases, 0); // else // return null; //} //public ClueNode GetClueNodeFromPhrases(string[] cluePhrases) //{ // if (Clues.ContainsKey(cluePhrases[0]) != false) // return Clues[cluePhrases[0]].GetNode(cluePhrases, 0); // else // return null; //} //public List<ClueNode> GetClueNodeFromPartialPhrase(string[] cluePhrases) // Compared with GetClueNodeFromPhrases(), this function doesn't assume the last keyword phrase to be exact //{ // // Make a partial copy // string[] partialPhrases = null; // Array.Copy(cluePhrases, partialPhrases, cluePhrases.Length - 1); // // Get node up till that partial copy // ClueNode node = null; // if (Clues.ContainsKey(partialPhrases[0]) != false) // node = Clues[partialPhrases[0]].GetNode(partialPhrases, 0); // else // return null; // // Check result // if (node != null) // { // // Find partial matches // List<ClueNode> partialMatches = new List<ClueNode>(); // string partialPhrase = cluePhrases[cluePhrases.Length - 1]; // foreach (KeyValuePair<string, ClueNode> entry in node.Children) // { // if(entry.Key.IndexOf(partialPhrase) == 0) // partialMatches.Add(entry.Value); // } // if (partialMatches.Count != 0) return partialMatches; // else return null; // } // else // return null; //} //#endregion #endregion #region Search Functions /// <summary> /// Given a clue, find any documents under that clue, or return null if not a valid clue /// </summary> /// <returns></returns> private List <Document> GetMatchingClueDocuments(string clue) { string[] fragments = SeperateClueFragments(clue.ToLower()); // Single fragment clue if (fragments.Length == 1) { if (Fragments.ContainsKey(fragments[0]) == true) { return(Fragments[fragments[0]].Documents.ToList()); } else { return(null); } } // Multiple fragment clue else { foreach (KeyValuePair <string, List <Document> > fragmentScope in FragmentScopes.Data) { if (ClueHelper.IsClueFragmentsMatching(fragments, SeperateClueFragments(fragmentScope.Key)) == true) { return(fragmentScope.Value); } } return(null); } }
public void RemoveDocumentClue(string clue, Document doc) { string[] fragments = ClueHelper.SeperateClueFragments(clue); // Remove from scope if (fragments.Length > 1) { FragmentScopes.Remove(clue, doc); } // Remove from fragments foreach (string fragment in fragments) { if (Fragments.ContainsKey(fragment) == false) { throw new InvalidOperationException("Key/Value isn't balanced for current operation doesn't have a previous counterpart."); } else { Fragments[fragment].Documents.Remove(doc); } // Remove from that fragment's scope if it's no longer used by anyone if (FragmentScopes.Get(clue) == null) { Fragments[fragment].FragmentScopes.Remove(clue); } } // Remove clue from collection if not used by others if (FragmentScopes.Get(clue) == null) { AllClues.Remove(clue); } }
// Given a particular clue string (e.g. A-B-C) for the document, record it; This clue constraints a fragment scope for that particular document // Input clue stirng can be in any order (e.g. C-A-B) public void AddDocumentClue(string clue, Document doc) { // Lower case is required clue = clue.ToLower(); // Condition on quantity of fragments List <string> fragments = ClueHelper.SeperateClueFragments(clue); // Add to all collection Clue addedOrExisting = ClueSet.Add(clue); // Add to scope if (fragments.Count > 1) { FragmentScopes.Add(addedOrExisting, doc); } // Add to fragments foreach (string fragment in fragments) { if (Fragments.ContainsKey(fragment)) { Fragments[fragment].Documents.Add(doc); } else { Fragments[fragment] = new FragmentInfo(fragment, doc); } Fragments[fragment].FullClues.Add(addedOrExisting); } }
// Given a particular clue A-B-C for the document; This clue constraints a fragment scope for that particular document public void AddDocumentClue(string clue, Document doc) // Assumed clue lower cased { string[] fragments = ClueHelper.SeperateClueFragments(clue); // Add to scope if (fragments.Length > 1) { FragmentScopes.Add(clue, doc); } // Add to fragments foreach (string fragment in fragments) { if (Fragments.ContainsKey(fragment)) { Fragments[fragment].Documents.Add(doc); } else { Fragments[fragment] = new FragmentInfo(fragment, doc); } Fragments[fragment].FragmentScopes.Add(clue); } // Add to all collection AllClues.Add(clue); // Notice by design (i.e. from where this function is called) clue is guaranteed to be non-duplicate to other already added ones; E.g. if it's manually created in clue creator we will rearrange it if it matches any existing ones. }