public async Task <UserActivitiesContainer> GetUserActivitiesAsync(ulong userID, DateTime?period = null)
        {
            using var scope = _scopeFactory.CreateScope();

            var activitiesDB = scope.ServiceProvider.GetRequiredService <IClanActivitiesDB>();

            var user = await activitiesDB.GetUserWithActivitiesAsync(userID, period);

            if (user is null)
            {
                return(null);
            }

            var activities = user.Characters.SelectMany(c => c.ActivityUserStats.Select(z => z.Activity)).Distinct();

            ConcurrentDictionary <int, int> activityCounter = new();

            var chunks = activities.Chunk(activities.Count() / 8 + 1);

            var tasks = chunks.Select(x => Task.Run(() =>
            {
                foreach (var activity in x)
                {
                    activityCounter.AddOrUpdate(activity.ActivityType, 1, (k, v) => v + 1);
                }
            }));

            var classes = user.Characters.Select(x => new ClassCounter
            {
                Class = (DestinyClass)x.Class,
                Count = x.ActivityUserStats.Count
            }).OrderByDescending(x => x.Count);

            await Task.WhenAll(tasks);

            var modeCounters = new ModeCountersContainer
            {
                Counters = activityCounter.Select(x => new ModeCounter
                {
                    ActivityMode = (DestinyActivityModeType)x.Key,
                    Count        = x.Value
                }).OrderByDescending(x => x.Count)
            };

            return(new UserActivitiesContainer
            {
                UserName = user.UserName,
                ClassCounters = classes,
                ModeCounters = modeCounters
            });
        }
        public async Task <UserPartnersContainer> GetUserPartnersAsync(ulong userID, DateTime?period = null)
        {
            using var scope = _scopeFactory.CreateScope();

            var activitiesDB = scope.ServiceProvider.GetRequiredService <IClanActivitiesDB>();

            var user = await activitiesDB.GetUserWithActivitiesAndOtherUserStatsAsync(userID, period);

            if (user is null)
            {
                return(null);
            }

            var allActivities  = user.Characters.SelectMany(x => x.ActivityUserStats.Select(y => y.Activity)).Distinct();
            var coopActivities = allActivities.Where(x => x.ActivityUserStats.Any(y => !user.Characters.Any(c => c.CharacterID == y.CharacterID)));

            var allUsers = await activitiesDB.GetUsersWithCharactersAsync();

            var coopUsers = allUsers.Where(x => x.UserID != user.UserID);

            ConcurrentDictionary <long, ConcurrentDictionary <int, int> > activityCounter = new();

            foreach (var partner in coopUsers)
            {
                activityCounter.TryAdd(partner.UserID, new());
            }

            var chunks = coopActivities.Chunk(coopActivities.Count() / 8 + 1);

            var tasks = chunks.Select(x => Task.Run(() =>
            {
                foreach (var activity in x)
                {
                    foreach (var partner in coopUsers)
                    {
                        if (activity.ActivityUserStats.Any(y => partner.Characters.Any(c => c.CharacterID == y.CharacterID)))
                        {
                            activityCounter[partner.UserID].AddOrUpdate(activity.ActivityType, 1, (k, v) => v + 1);
                        }
                    }
                }
            }));

            var allCount  = allActivities.Count();
            var coopCount = coopActivities.Count();

            var userNames = coopUsers.ToDictionary(x => x.UserID, x => x.UserName);

            await Task.WhenAll(tasks);

            var partners = activityCounter.ToDictionary(
                x => x.Key,
                x => x.Value.Sum(y => y.Value))
                           .Where(x => x.Value > 0)
                           .OrderByDescending(x => x.Value);

            ConcurrentBag <(string, int[])> topPartnersTypeCounters = new();
            var containerTasks = partners.Take(8)
                                 .Select(x => Task.Run(() =>
            {
                var container = new ModeCountersContainer
                {
                    Counters = activityCounter[x.Key]
                               .Select(y => new ModeCounter
                    {
                        ActivityMode = (DestinyActivityModeType)y.Key,
                        Count        = y.Value
                    })
                };

                topPartnersTypeCounters.Add((userNames[x.Key], container.TypeCounters));
            }));

            var partnersCounters = partners
                                   .Select(x => new PartnersCounter
            {
                UserName = userNames[x.Key],
                Count    = x.Value
            });

            await Task.WhenAll(containerTasks);

            return(new UserPartnersContainer
            {
                UserName = user.UserName,
                TotalCount = allCount,
                CoopCount = coopCount,
                Partners = partnersCounters,
                TopPartners = topPartnersTypeCounters
            });
        }