public List <StatisticCacheDTO> GetStatisticCaches(StatisticFunc statisticFunc, DateTime?from, DateTime?to)
        {
            var allMessages = messageService.GetAllMessages().OrderBy(o => o.NormalizedSentDate).Decompile();

            DateTime firstMessageDate;
            DateTime lastMessageDate;

            if (from != null)
            {
                var firstMessage = allMessages.FirstOrDefault(o => o.NormalizedSentDate >= from.Value);
                if (firstMessage == null)
                {
                    return(new List <StatisticCacheDTO>());
                }

                firstMessageDate = firstMessage.NormalizedSentDate;
            }
            else
            {
                firstMessageDate = allMessages.FirstOrDefault().NormalizedSentDate;
            }

            if (to != null)
            {
                var lastMessage = allMessages.LastOrDefault(o => o.NormalizedSentDate <= to.Value);
                if (lastMessage == null)
                {
                    return(new List <StatisticCacheDTO>());
                }

                lastMessageDate = lastMessage.NormalizedSentDate;
            }
            else
            {
                lastMessageDate = allMessages.LastOrDefault().NormalizedSentDate;
            }

            if (firstMessageDate > lastMessageDate)
            {
                return(new List <StatisticCacheDTO>());
            }

            var caches = mainDbContext.StatisticCaches
                         .Include(o => o.ForSenders)
                         .Where(o => o.StatisticName == statisticFunc.Name)
                         .Where(o => o.ForDate >= firstMessageDate && o.ForDate <= lastMessageDate).ToList();

            var senders = messageService.GetAllSenders();

            var days = Math.Round((lastMessageDate - firstMessageDate).TotalDays) + 1;

            if (caches.Count < days)
            {
                var messages = messageService.GetAllMessages().FilterDateRange(firstMessageDate, lastMessageDate).ToList();
                for (int i = 0; i < days; i++)
                {
                    var date = firstMessageDate.AddDays(i);

                    if (caches.Find(o => o.ForDate == date) == null)
                    {
                        var newCache = new StatisticCache()
                        {
                            StatisticName = statisticFunc.Name,
                            ForDate       = date,
                            ForSenders    = senders.Select(sender => new StatisticCacheForSender()
                            {
                                SenderId = sender.Id,
                                Total    = statisticFunc.Func(messages.AsQueryable().Filter(sender, date))
                            }).ToList()
                        };
                        mainDbContext.StatisticCaches.Add(newCache);
                        caches.Add(newCache);
                    }
                }

                mainDbContext.SaveChanges();
            }

            var result = caches.Select(o => new StatisticCacheDTO()
            {
                Id               = o.Id,
                ForDate          = o.ForDate,
                StatisticName    = o.StatisticName,
                TotalsForSenders = senders.ToDictionary(s => s.Id, s =>
                {
                    var forSender = o.ForSenders.FirstOrDefault(f => f.Sender == s);
                    if (forSender != null)
                    {
                        return(forSender.Total);
                    }
                    else
                    {
                        return(0);
                    }
                })
            }).ToList();

            return(result);
        }
Пример #2
0
        private Statistic Get(StatisticFunc statisticFunc, List <Sender> senders, DateTime?fromDate, DateTime?toDate, string groupingPeriod)
        {
            List <DateTime> timePeriods;
            Dictionary <int, List <float> > valuesBySendersOnTimePeriods;

            if (groupingPeriod == "timeOfDay" || groupingPeriod == "hour")
            {
                var filteredMessages = messageService.GetAllMessages().FilterDateRange(fromDate, toDate).ToList();


                Func <Message, DateTime> groupingSelector = null;
                switch (groupingPeriod)
                {
                case "timeOfDay":
                    groupingSelector = o => new DateTime(2021, 1, 1, o.SentDateTime.Hour, 0, 0);
                    break;

                case "hour":
                    groupingSelector = o => new DateTime(o.SentDateTime.Year, o.SentDateTime.Month, o.SentDateTime.Day, o.SentDateTime.Hour, 0, 0);
                    break;

                default:
                    throw new ArgumentOutOfRangeException("Grouping period cannot be: " + groupingPeriod);
                }

                var tp = timePeriods = filteredMessages.GroupBy(groupingSelector).Distinct().Select(o => o.Key).OrderBy(o => o).ToList();

                valuesBySendersOnTimePeriods =
                    senders
                    .ToDictionary(o => o.Id, o => tp
                                  .Select(p => filteredMessages
                                          .AsQueryable()
                                          .Filter(o)
                                          .Where(o => groupingSelector(o) == p))
                                  .AsParallel()
                                  .AsOrdered()
                                  .Select(i => (float)statisticFunc.Func(i))
                                  .ToList());
            }
            else
            {
                var caches = statisticCacheService.GetStatisticCaches(statisticFunc, fromDate, toDate);

                Func <StatisticCacheDTO, DateTime> groupingSelector = null;
                switch (groupingPeriod)
                {
                case "date":
                    groupingSelector = o => o.ForDate;
                    break;

                case "week":
                    groupingSelector = o => o.ForDate.AddDays(-(((int)o.ForDate.DayOfWeek + 6) % 7));
                    break;

                case "month":
                    groupingSelector = o => new DateTime(o.ForDate.Year, o.ForDate.Month, 1);
                    break;

                default:
                    throw new ArgumentOutOfRangeException("Grouping period cannot be: " + groupingPeriod);
                }

                var tp = timePeriods = caches.AsEnumerable().GroupBy(groupingSelector).Distinct().Select(o => o.Key).OrderBy(o => o).ToList();

                valuesBySendersOnTimePeriods =
                    senders
                    .ToDictionary(o => o.Id, s => timePeriods
                                  .Select(p => caches
                                          .Where(o => groupingSelector(o) == p)
                                          .Sum(o => (float)o.TotalsForSenders[s.Id]))
                                  .ToList());
            }

            // izbaci sve dane/sate/tjedne/mjesece u kojima ima totalno 0 poruka/rijeci/znakova
            for (int i = 0; i < timePeriods.Count; i++)
            {
                if (valuesBySendersOnTimePeriods.Sum(o => o.Value[i]) == 0)
                {
                    timePeriods.RemoveAt(i);
                    valuesBySendersOnTimePeriods.ForEach(o => o.Value.RemoveAt(i));
                    i--;
                }
            }

            var          totalBySenders      = valuesBySendersOnTimePeriods.ToDictionary(o => o.Key, o => o.Value.Sum());
            var          total               = totalBySenders.Values.Sum();
            List <float> totalsOnTimePeriods = new List <float>();

            for (int i = 0; i < timePeriods.Count; i++)
            {
                totalsOnTimePeriods.Add(valuesBySendersOnTimePeriods.Sum(o => o.Value[i]));
            }

            var result = new Statistic()
            {
                Total  = total,
                Filter = new Filter()
                {
                    FromDate       = fromDate,
                    ToDate         = toDate,
                    GroupingPeriod = groupingPeriod,
                    Per            = "none"
                },
                Senders        = senders.ToDictionary(s => s.Id, s => SenderDTO.From(s)),
                TotalBySenders = totalBySenders,
                TimePeriods    = timePeriods,
                ValuesBySendersOnTimePeriods = valuesBySendersOnTimePeriods,
                TotalsOnTimePeriods          = totalsOnTimePeriods,
                StatisticName = statisticFunc.Name
            };

            return(result);
        }