//#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 ClueHelper() { Fragments = new Dictionary <string, FragmentInfo>(); FragmentScopes = new MultiDict <string, Document>(); ClueSet = new ClueSet(); ClueManager = this; }
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); } }
/// <summary> /// Given a clue string, get the clue corresponding to it /// Input clue stirng can be in any order (e.g. C-A-B) /// </summary> /// <param name="clueString"></param> /// <returns></returns> public Clue Get(string clueString) { List <string> segments = ClueHelper.SeperateClueFragments(clueString); string[] fullSet = segments.ToArray(); string seg; for (int i = 0; i < segments.Count; i++) { seg = segments[i]; if (CluesTree.ContainsKey(seg)) { segments.RemoveAt(i); return(CluesTree[seg].GetClue(segments)); } } return(null); }
/// <summary> /// Given a clue string, add it to current set /// Input clue stirng can be in any order (e.g. C-A-B) /// </summary> /// <param name="clueString"></param> public Clue Add(string clueString) { List <string> segments = ClueHelper.SeperateClueFragments(clueString); string[] fullSet = segments.ToArray(); string seg; for (int i = 0; i < segments.Count; i++) { seg = segments[i]; if (CluesTree.ContainsKey(seg)) { segments.RemoveAt(i); return(CluesTree[seg].AddClue(segments, fullSet)); } } seg = segments[0]; CluesTree[seg] = new ClueNode(); segments.RemoveAt(0); return(CluesTree[seg].AddClue(segments, fullSet)); }
/// <summary> /// Given a sequence of fragments, find all fragment groups that are either equal or bigger than that sequence; return null if no exact or partial match can be found; Cross-overlap is not legal /// </summary> private List <string[]> GetMatchingScopes(string[] fragments) { List <string[]> matchingScopes = new List <string[]>(); foreach (KeyValuePair <string, List <Document> > fragmentScope in FragmentScopes.Data) { string[] compareFragments = ClueHelper.SeperateClueFragments(fragmentScope.Key); if (ClueHelper.IsClueFragmentsContains(compareFragments, fragments) == true) { matchingScopes.Add(compareFragments); } } // If we have any matching scope if (matchingScopes.Count > 0) { return(matchingScopes); } else { return(null); } }
// 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. }
public void Rename(string newClue) { // When a clue is renamed, it's just renamed; Documents are not affected by this operation for links are based on GUIDs Fragments = ClueHelper.SeperateClueFragments(newClue).ToArray(); }