/// <inheritdoc /> public async Task <IReadOnlyCollection <StageSweep> > GetSweepsAsync( Game game, bool untied, DateTime?startDate, DateTime?endDate, Stage?stage) { if (startDate > endDate) { throw new ArgumentOutOfRangeException(nameof(startDate), startDate, $"{nameof(startDate)} is greater than {nameof(endDate)}."); } var fullEntries = new List <EntryDto>(); foreach (var locStage in game.GetStages()) { var entries = await _readRepository .GetEntriesAsync(locStage) .ConfigureAwait(false); fullEntries.AddRange(entries); } var entriesGroups = fullEntries .Where(e => e.Date.HasValue) .GroupBy(e => (e.Stage, e.Level)) .ToDictionary(e => e.Key, e => e.ToList()); var playerKeys = await GetPlayersInternalAsync().ConfigureAwait(false); var sweepsRaw = new ConcurrentBag <(long playerId, DateTime date, Stage stage)>(); var dates = SystemExtensions .LoopBetweenDates( startDate ?? Extensions.GetEliteFirstDate(game), endDate ?? ServiceProviderAccessor.ClockProvider.Now, DateStep.Day) .GroupBy(d => d.DayOfWeek) .ToDictionary(d => d.Key, d => d); var tasks = new List <Task>(); foreach (var dow in SystemExtensions.Enumerate <DayOfWeek>()) { tasks.Add(Task.Run(() => { foreach (var currentDate in dates[dow]) { foreach (var stg in game.GetStages()) { if (stage == null || stg == stage) { sweepsRaw.AddRange( GetPotentialSweeps(untied, entriesGroups, currentDate, stg)); } } } })); } await Task.WhenAll(tasks).ConfigureAwait(false); var finalSweeps = new List <StageSweep>(); foreach (var(playerId, date, locStage) in sweepsRaw.OrderBy(f => f.date)) { var sweepMatch = finalSweeps.SingleOrDefault(s => s.Player.Id == playerId && s.Stage == locStage && s.EndDate == date); if (sweepMatch == null) { sweepMatch = new StageSweep(date, locStage, playerKeys[playerId]); finalSweeps.Add(sweepMatch); } sweepMatch.AddDay(); } return(finalSweeps); }