using System; using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using Portoa.Persistence; using VideoGameQuotes.Api; using VideoGameQuotes.Web.Models; namespace VideoGameQuotes.Web.Services { public interface IQuoteService { Game GetGame(int id); IEnumerable GetAllGames(); IEnumerable GetAllSystems(); IEnumerable GetAllPublishers(); IEnumerable GetAllCategories(); Quote SaveQuote(Quote quote); Quote GetQuote(int id); Publisher GetPublisher(int id); GamingSystem GetSystem(int systemId); Category GetCategory(int categoryId); IEnumerable GetRecentQuotes(int start, int end, out int totalCount); [CanBeNull] Quote GetRandomQuote(); IEnumerable GetBestQuotes(int start, int end, out int totalCount); Vote GetVoteOrCreateNew(Quote quote, User voter); IEnumerable GetBrowsableQuotes(BrowseModel model, int start, int end, out int totalCount); Quote GetQuoteForDayOfYear(int day); DefaultBrowseModel GetDefaultBrowseModel(); void Delete(int id); } public class QuoteService : IQuoteService { private readonly IRepository quoteRepository; private readonly IRepository gameRepository; private readonly IRepository systemRepository; private readonly IRepository publisherRepository; private readonly IRepository categoryRepository; private readonly IRepository voteRepository; private static readonly Random random = new Random(); private static readonly IDictionary quoteOfTheDayMap = new Dictionary(); public QuoteService( IRepository quoteRepository, IRepository gameRepository, IRepository systemRepository, IRepository publisherRepository, IRepository categoryRepository, IRepository voteRepository ) { this.quoteRepository = quoteRepository; this.categoryRepository = categoryRepository; this.voteRepository = voteRepository; this.gameRepository = gameRepository; this.systemRepository = systemRepository; this.publisherRepository = publisherRepository; } [UnitOfWork] public DefaultBrowseModel GetDefaultBrowseModel() { return new DefaultBrowseModel { TotalNumberOfCategories = categoryRepository.Records.Count(), TotalNumberOfSystems = systemRepository.Records.Count(), TotalNumberOfPublishers = publisherRepository.Records.Count(), TotalNumberOfGames = gameRepository.Records.Count(), TotalNumberOfQuotes = quoteRepository.Records.Count() }; } [UnitOfWork] public void Delete(int id) { quoteRepository.Delete(id); } [UnitOfWork] public Game GetGame(int id) { return gameRepository.FindById(id); } [UnitOfWork] public IEnumerable GetAllGames() { return gameRepository.Records; } [UnitOfWork] public IEnumerable GetAllSystems() { return systemRepository.Records; } [UnitOfWork] public IEnumerable GetAllPublishers() { return publisherRepository.Records; } [UnitOfWork] public IEnumerable GetAllCategories() { return categoryRepository.Records; } [UnitOfWork] public Quote SaveQuote(Quote quote) { return quoteRepository.Save(quote); } [UnitOfWork] public Quote GetQuote(int id) { return quoteRepository.FindById(id); } [UnitOfWork] public Publisher GetPublisher(int id) { return publisherRepository.FindById(id); } [UnitOfWork] public GamingSystem GetSystem(int systemId) { return systemRepository.FindById(systemId); } [UnitOfWork] public Category GetCategory(int categoryId) { return categoryRepository.FindById(categoryId); } [UnitOfWork] public IEnumerable GetRecentQuotes(int start, int end, out int totalCount) { totalCount = quoteRepository.Records.Count(); return quoteRepository .Records .OrderByDescending(quote => quote.Created) .Skip(start - 1) .Take(end - start + 1); } [UnitOfWork] public Quote GetRandomQuote() { var length = quoteRepository.Records.Count(); if (length == 0) { return null; } return GetRandomQuote(quoteRepository.Records); } private static Quote GetRandomQuote(IEnumerable quotes) { var length = quotes.Count(); if (length == 0) { return null; } return quotes .Skip(random.Next(length)) .Take(1) .Single(); } [UnitOfWork] public IEnumerable GetBestQuotes(int start, int end, out int totalCount) { totalCount = quoteRepository.Records.Count(); return quoteRepository.Records .OrderByDescending(quote => quote.Score) .ThenByDescending(quote => quote.UpVotes) .Skip(start - 1) .Take(end - start + 1); } [UnitOfWork] public Vote GetVoteOrCreateNew(Quote quote, User voter) { var vote = voteRepository.Records.SingleOrDefault(v => v.Quote == quote && v.Voter == voter); return vote ?? new Vote { Quote = quote, Voter = voter }; } [UnitOfWork] public IEnumerable GetBrowsableQuotes(BrowseModel model, int start, int end, out int totalCount) { var quotes = quoteRepository.Records; if (model.GameIds.Any()) { quotes = quotes.Where(quote => model.GameIds.Contains(quote.Game.Id)); } if (model.PublisherIds.Any()) { quotes = quotes.Where(quote => quote.Game.Publishers.Any(publisher => model.PublisherIds.Contains(publisher.Id))); } if (model.SystemIds.Any()) { quotes = quotes.Where(quote => quote.Game.Systems.Any(system => model.SystemIds.Contains(system.Id))); } if (model.CategoryIds.Any()) { quotes = quotes.Where(quote => quote.Categories.Any(category => model.CategoryIds.Contains(category.Id))); } totalCount = quotes.Count(); return quotes.OrderByDescending(quote => quote.Score).ThenBy(quote => quote.UpVotes).Skip(start - 1).Take(end - start + 1); } [UnitOfWork, CanBeNull] public Quote GetQuoteForDayOfYear(int day) { if (!quoteOfTheDayMap.ContainsKey(day)) { quoteOfTheDayMap[day] = GetRandomQuote(quoteRepository.Records.Where(quote => quote.Score > 0)); } return quoteOfTheDayMap[day]; } } }