private static Int32 Load <T, TKey>(ICollection <T> units, NameDatabase <T, TKey> database) where TKey : IEquatable <TKey> { var count = 0; foreach (var unit in units) { if (database.Add(unit)) { ++count; } } return(count); }
} // relax_spelling(...) private static HashSet <String> Relax(HashSet <String> names) { var result = new HashSet <String>(names); foreach (var name in names) { var stage1 = NameDatabase <T, TKey> .RelaxToLowercase(name); var stage2 = NameDatabase <T, TKey> .RelaxSpelling(stage1); result.Add(stage1); result.Add(stage2); } // for (...) return(result); }
private HashSet <String> Relax(T unit, ref HashSet <String> strictNames) { var result = this.BuildNames(unit); var doCancel = false; this.OnRelaxing(unit, ref doCancel); if (doCancel) { return(result); } result = NameDatabase <T, TKey> .Relax(result); this.OnRelaxed(unit, result, ref strictNames); foreach (var name in strictNames) { result.Add(name); } return(result); } // relax(...)
} // try_find(...) public Boolean Add(T unit) { var doCancel = false; this.OnLoading(unit, ref doCancel); if (doCancel) { return(false); } var key = this.BuildKey(unit); var names = this.BuildNames(unit); // Names for logging purposes. var strictNames = new HashSet <String>(); var treeNames = this.Relax(unit, ref strictNames); var treeSynonyms = NameDatabase <T, TKey> .Relax(strictNames); if (this.database.ContainsKey(key)) { App.Warnings.Push($"Unit with id ({key}) already exists."); return(false); } // if (...) else if (this.nameTree.ContainsAny(treeNames)) { App.Warnings.Push($"Unit with a similar name ({String.Join(", ", names)}) already exists."); return(false); } // if (...) else { this.database.Add(key, unit); this.nameTree.TryAddMany(key, treeNames); foreach (var explicitSynonym in treeSynonyms) { this.nameTree.AddSynonym(key, explicitSynonym); } this.OnLoaded(unit); return(true); } // if (...) } // add(...)
public T Find(String query, Func <T, Boolean> filter) { var lowercase = NameDatabase <T, TKey> .RelaxToLowercase(query); var misspelled = NameDatabase <T, TKey> .RelaxSpelling(lowercase); bool isValid = false; // Stage 0: prefix tree search. this.suggestions.Clear(); var searchA = this.nameTree.Search(query); if (!Object.ReferenceEquals(searchA, null)) { var unit = this.AsSingle(searchA, filter, ref isValid); if (isValid) { return(unit); } else { foreach (var synonymKey in searchA.SynonymKeys) { var maybe = this.database[synonymKey]; var names = this.BuildNames(maybe); var name = names.Count == 0 ? "??" : names.First(); if (filter == null || filter(maybe)) { this.suggestions.Add(name); } } } } // if (...) // Stage 1: lowercase lookup. var searchB = this.nameTree.Search(lowercase); if (!Object.ReferenceEquals(searchB, null)) { var unit = this.AsSingle(searchB, filter, ref isValid); if (isValid) { this.suggestions.Clear(); return(unit); } App.Suggestions.Push($"Multiple units match the specified query: {lowercase}."); return(default(T)); } // if (...) // Stage 2: misspelled lookup. var searchC = this.nameTree.Search(misspelled); if (!Object.ReferenceEquals(searchC, null)) { var unit = this.AsSingle(searchC, filter, ref isValid); if (isValid) { this.suggestions.Clear(); return(unit); } App.Suggestions.Push($"Multiple units match the specified query: {misspelled}."); return(default(T)); } // if (...) return(default(T)); } // try_find(...)