public static BundleWithResponse BundleWithTags(string text, int quantity, SqlConnection connection, ILogger log) { string[] itemAndTags = text.Split(" with tags ", StringSplitOptions.RemoveEmptyEntries); if (itemAndTags.Length != 2) { return(new BundleWithResponse()); } string newItem = itemAndTags[0].Trim(); TagSet existingItemTags = new TagSet(itemAndTags[1]); // Take a string of words: "Green motor driver" // Extract a HashSet of tags: HashSet<string> = { "Green", "motor", "driver" } // Format as params for SQL query, to defend against SQL injection attacks: // "@param2,@param3,@param4" string paramList = string.Join(",", existingItemTags.Select((tag, index) => $"@param{index+2}")); log.LogInformation(paramList); int maxResults = 3; var queryString = $@" SELECT TOP (@param1) i.Name, i.Quantity, i.Row, i.Col, i.IsSmallBox, t.TagsMatched FROM dbo.Items i JOIN ( SELECT NameKey, COUNT(NameKey) TagsMatched FROM dbo.Tags WHERE Tag IN({paramList}) GROUP BY NameKey ) t ON i.NameKey = t.NameKey ORDER BY t.TagsMatched DESC"; List <TaggedItem> items = new List <TaggedItem>(); using (SqlCommand command = new SqlCommand()) { command.Connection = connection; command.CommandText = queryString; command.Parameters.AddWithValue("@param1", maxResults); int index = 2; foreach (string tag in existingItemTags) { command.Parameters.AddWithValue($"@param{index++}", tag); } SqlDataReader reader = command.ExecuteReader(); try { while (reader.Read()) { items.Add(new TaggedItem { Name = (string)reader["Name"], Row = (int)reader["Row"], Col = (int)reader["Col"], TagsMatched = (int)reader["TagsMatched"], IsSmallBox = (bool)reader["IsSmallBox"] }); } } catch (Exception ex) { log.LogInformation(ex.Message); return(new BundleWithResponse()); } finally { reader.Close(); } } IEnumerable <TaggedItem> fullyMatchedItems = items.Where(a => a.TagsMatched.Value == existingItemTags.Count); if (fullyMatchedItems.Count() == 1) { TaggedItem existingItem = fullyMatchedItems.First(); Item insertItem = new Item( newItem, quantity, existingItem.Row.Value, existingItem.Col.Value, existingItem.IsSmallBox.Value); TagSet newItemTags = new TagSet(newItem); InsertItemResponse resp = InsertItemWithTags(insertItem, newItemTags, connection, log); if (resp.Success) { return(new BundleWithResponse(true, newItem, quantity, existingItem.Name, insertItem.Row, insertItem.Col)); } else { return(new BundleWithResponse(false, newItem, quantity, existingItem.Name)); } } return(new BundleWithResponse()); }
public static bool TryGetTagsInfo(string info, int boxIndex, out int startIndex, out TagSet tags) { string tagsTag = " with tags "; startIndex = info.IndexOf(tagsTag); if (startIndex == -1) { tags = new TagSet(); return(false); } string tagsString; int tagsStartIndex = startIndex + tagsTag.Length; if (startIndex < boxIndex) { tagsString = info.Substring(tagsStartIndex, boxIndex - tagsStartIndex); } else { tagsString = info.Substring(tagsStartIndex); } if (!string.IsNullOrEmpty(tagsString)) { tags = new TagSet(tagsString); return(true); } else { tags = new TagSet(); return(false); } }
public static FindTagsResponse FindTags(TagSet tagSet, SqlConnection connection, ILogger log, int maxResults = 10) { if (tagSet.Count == 0) { return(new FindTagsResponse(-1, null)); } // Take a string of words: "Green motor driver" // Extract a HashSet of tags: HashSet<string> = { "Green", "motor", "driver" } // Format as params for SQL query, to defend against SQL injection attacks: // "@param2,@param3,@param4" string paramList = string.Join(",", tagSet.Select((_, index) => $"@param{index + 2}")); log.LogInformation(paramList); var queryString = $@" SELECT i.NameKey, i.Name, i.Quantity, i.Row, i.Col, t.TagsMatched FROM dbo.Items i JOIN ( SELECT NameKey, COUNT(NameKey) TagsMatched FROM dbo.Tags WHERE Tag IN({paramList}) GROUP BY NameKey ) t ON i.NameKey = t.NameKey ORDER BY t.TagsMatched DESC"; using (SqlCommand command = new SqlCommand()) { command.Connection = connection; command.CommandText = queryString; command.Parameters.AddWithValue("@param1", maxResults); int index = 2; foreach (string tag in tagSet) { command.Parameters.AddWithValue($"@param{index++}", tag); } SqlDataReader reader = command.ExecuteReader(); try { int i = 0; List <int[]> coordsAndMatches = new List <int[]>(); while (reader.Read() && i++ < maxResults) { coordsAndMatches.Add(new int[] { (int)reader["Row"], (int)reader["Col"], (int)reader["TagsMatched"] }); } return(new FindTagsResponse(tagSet.Count, coordsAndMatches)); } catch (Exception ex) { log.LogInformation(ex.Message); return(new FindTagsResponse(tagSet.Count, null)); } finally { reader.Close(); } } }