using System; using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Props.Data; using Props.Models.Search; using Props.Options; using Props.Shop.Framework; namespace Props.Services.Modules { public class LiveMetricsManager : IMetricsManager { private MetricsOptions metricsOptions; private ILogger logger; private ApplicationDbContext dbContext; private IQueryable leastPopularProductListings; private IQueryable leastPopularQueryWords; public LiveMetricsManager(ApplicationDbContext dbContext, ILogger logger, IConfiguration configuration) { this.metricsOptions = configuration.GetSection(MetricsOptions.Metrics).Get(); this.logger = logger; this.dbContext = dbContext; leastPopularProductListings = from listing in dbContext.ProductListingInfos orderby listing.Hits ascending select listing; leastPopularQueryWords = from word in dbContext.QueryWords orderby word.Hits ascending select word; } public IEnumerable RetrieveTopListings(int max) { if (dbContext.ProductListingInfos == null) return null; return (from l in dbContext.ProductListingInfos orderby l.Hits descending select l).Take(max); } public IEnumerable RetrieveCommonKeywords(int max) { if (dbContext.QueryWords == null) return null; return (from k in dbContext.QueryWords orderby k.Hits descending select k.Word).Take(max); } public void RegisterSearchQuery(string query) { query = query.ToLower(); string[] tokens = query.Split(' '); QueryWordInfo[] wordInfos = new QueryWordInfo[tokens.Length]; for (int wordIndex = 0; wordIndex < tokens.Length; wordIndex++) { QueryWordInfo queryWordInfo = dbContext.QueryWords.Where((k) => k.Word.ToLower().Equals(tokens[wordIndex])).SingleOrDefault() ?? new QueryWordInfo(); if (queryWordInfo.Hits == 0) { queryWordInfo.Word = tokens[wordIndex]; dbContext.QueryWords.Add(queryWordInfo); } queryWordInfo.Hits += 1; wordInfos[wordIndex] = queryWordInfo; } for (int wordIndex = 0; wordIndex < tokens.Length; wordIndex++) { for (int beforeIndex = 0; beforeIndex < wordIndex; beforeIndex++) { wordInfos[wordIndex].Preceding.Add(wordInfos[beforeIndex]); } for (int afterIndex = wordIndex; afterIndex < tokens.Length; afterIndex++) { wordInfos[wordIndex].Following.Add(wordInfos[afterIndex]); } } CullQueryWords(); dbContext.SaveChanges(); } public void RegisterProductListing(ProductListing productListing, string shopName) { ProductListingInfo productListingInfo = (from info in dbContext.ProductListingInfos where info.ProductListingIdentifier.Equals(productListing.Identifier) select info).SingleOrDefault() ?? new ProductListingInfo(); if (productListingInfo.Hits == 0) { dbContext.Add(productListingInfo); } productListingInfo.ShopName = shopName; productListingInfo.ProductListing = productListing; productListingInfo.ProductListingIdentifier = productListing.Identifier; productListingInfo.Hits += 1; CullProductListings(); dbContext.SaveChanges(); } private void CullProductListings() { int surplus = dbContext.ProductListingInfos.Count() - metricsOptions.MaxProductListings; if (surplus > 0) { dbContext.RemoveRange(leastPopularProductListings.Take(surplus)); } } private void CullQueryWords() { int surplus = dbContext.QueryWords.Count() - metricsOptions.MaxQueryWords; if (surplus > 0) { dbContext.RemoveRange(leastPopularQueryWords.Take(surplus)); } } } }