/// <summary> /// Initializes a new instance of the <see cref="StringKeywordSuggestion"/> class. /// </summary> /// <param name="keywordValue">Sets value of keyword</param> /// <param name="sourceId">Id of the source that is creating this suggestion</param> /// <param name="sourceName">Optional id of the source. If not provided the name will be </param> public StringKeywordSuggestion(string keywordValue, Guid sourceId, string sourceName = "") { if (keywordValue.Trim().Equals(string.Empty)) { throw new ArgumentException("KeywordValue should not be an empty string"); } if (sourceId == null) { throw new ArgumentNullException("Source id is not set"); } if (keywordValue.Equals(string.Empty)) { throw new ArgumentException(); } this.objectValue = new SimpleStringObject(keywordValue); this.sourceId = sourceId; this.sourceName = sourceName.Equals(string.Empty) ? this.sourceId.ToString() : this.sourceName = sourceName; this.rankValue = 1; this.relevance = -1; }
/// <summary> /// Suggests description instances from the defined in Suggester sources based on one or more semantic objects /// </summary> /// <param name="semanticObjects">RDF based concrete semantic object</param> /// <param name="sourceFilter">if Null all sources are used, if set only those set are processed</param> /// <returns>Returns collection of suggested description objects (such as keywords, RDF statements, etc.)</returns> public List<ISuggestionInstance> GetSuggestions(ISemanticObject[] semanticObjects, Guid[] sourceFilter = null) { Dictionary<string, Tuple<ISuggestionInstance, double>> CombinedCollection = new Dictionary<string, Tuple<ISuggestionInstance, double>>(); double maxRelevanceSum = 0; double minRelevanceValue = double.MaxValue; const string combinedSourceName = "Multiple sources"; Guid combinedGuid = Guid.NewGuid(); foreach (var nextSource in this.sources) { if (sourceFilter == null || sourceFilter.Contains(nextSource.Guid)) { foreach (var nextResult in nextSource.GetSuggestions(semanticObjects)) { double combinedrelevance; if (CombinedCollection.ContainsKey(nextResult.GetTextValue())) { var oldvalue = CombinedCollection[nextResult.GetTextValue()]; combinedrelevance = oldvalue.Item2 + nextResult.Relevance; // HACK - think how this should be when RDF suggestions sources implemented. Should we flatter them like this or do something else. var combinedResult = new StringKeywordSuggestion(nextResult.GetTextValue(), combinedGuid, combinedSourceName); nextResult.Rank = nextResult.Rank + oldvalue.Item1.Rank; CombinedCollection[nextResult.GetTextValue()] = new Tuple<ISuggestionInstance, double>(combinedResult, combinedrelevance); } else { combinedrelevance = nextResult.Relevance; CombinedCollection.Add(nextResult.GetTextValue(), new Tuple<ISuggestionInstance, double>(nextResult, combinedrelevance)); } if (combinedrelevance > maxRelevanceSum) { maxRelevanceSum = combinedrelevance; } if (combinedrelevance < minRelevanceValue) { minRelevanceValue = combinedrelevance; } } } } // now normalize relevance var readyList = new List<ISuggestionInstance>(); foreach (var nextSuggestion in CombinedCollection) { // map 0...max to 0..100; double newrelevance = (maxRelevanceSum * nextSuggestion.Value.Item2 == 0) ? 0 : 100 / maxRelevanceSum * nextSuggestion.Value.Item2; var nextsuggestion = nextSuggestion.Value.Item1; nextsuggestion.Relevance = newrelevance; readyList.Add(nextsuggestion); } readyList.Sort(delegate (ISuggestionInstance x, ISuggestionInstance y) { return y.Relevance.CompareTo(x.Relevance); // descending sort }); return readyList; }