Esempio n. 1
0
        public void GroupOddDrawCompetitors()
        {
            var settings = new DistanceDrawSettings
            {
                GroupMode = DistanceDrawGroupMode.Time,
                GroupSize = 2
            };

            var sortedCompetitors = expert.SortDrawCompetitors(distance, drawCompetitors, settings);
            var groups            = expert.GroupDrawCompetitors(distance, 1, sortedCompetitors, settings);

            Assert.AreEqual(3, groups.Count);
            Assert.AreEqual(2, groups[0].Count);
            Assert.AreEqual(2, groups[1].Count);
            Assert.AreEqual(1, groups[2].Count);

            Assert.IsTrue(groups.SelectMany(g => g).SequenceEqual(new[]
            {
                drawCompetitors[1],
                drawCompetitors[4],
                drawCompetitors[0],
                drawCompetitors[3],
                drawCompetitors[2]
            }));
        }
        public async Task <DistanceDrawSettings> GetSettingsOrDefaultAsync(Guid competitionId)
        {
            var settings = await Settings.FirstOrDefaultAsync(s => s.CompetitionId == competitionId);

            if (settings == null)
            {
                settings = new DistanceDrawSettings
                {
                    CompetitionId = competitionId
                };
                context.DistanceDrawSettings.Add(settings);
            }
            return(settings);
        }
Esempio n. 3
0
        public override Task DrawCompetitorGroupAsync(Distance distance, IReadOnlyCollection <Guid> distanceCombinations, int round, IList <CompetitorBase> competitors,
                                                      ICompetitionContext context, DistanceDrawSettings settings)
        {
            switch (settings.Mode)
            {
            case DistanceDrawMode.Random:
            case DistanceDrawMode.SwitchLanesOrRandom:
                competitors.Shuffle();
                return(Task.FromResult <object>(null));

            default:
                throw new DrawModeNotSupportedException();
            }
        }
Esempio n. 4
0
        public void DrawOddQuartetsRandomReverse()
        {
            var settings = new DistanceDrawSettings
            {
                GroupMode      = DistanceDrawGroupMode.Time,
                GroupSize      = 2,
                ReverseFilling = true
            };

            var sortedCompetitors = expert.SortDrawCompetitors(distance, drawCompetitors, settings);
            var groups            = expert.GroupDrawCompetitors(distance, 1, sortedCompetitors, settings);

            var competitorGroups = new List <IReadOnlyList <CompetitorBase> >();

            foreach (var group in groups)
            {
                var competitorGroup = group.Select(g => g.Competitor).ToList();
                expert.DrawCompetitorGroupAsync(distance, new[] { distanceCombination.Id }, 1, competitorGroup, context, settings).Wait();
                competitorGroups.Add(competitorGroup);
            }

            var heats = expert.FillCompetitorsInHeatsAsync(distance, new[] { distanceCombination.Id }, 1, competitorGroups, context, settings).Result;
            var races = heats.SelectMany(r => r.Value).ToList();

            Assert.IsTrue(Enumerable.Range(distance.FirstHeat, 4).SequenceEqual(heats.Keys));
            Assert.AreEqual(2, heats[9].Count);
            Assert.AreEqual(2, heats[10].Count);
            Assert.AreEqual(0, heats[11].Count);
            Assert.AreEqual(1, heats[12].Count);
            Assert.AreEqual(5, races.Count);
            Assert.AreEqual(0, races[0].Lane);
            Assert.AreEqual(1, races[1].Lane);
            Assert.AreEqual(0, races[2].Lane);
            Assert.AreEqual(1, races[3].Lane);
            Assert.AreEqual(0, races[4].Lane);
        }
        public async Task <IReadOnlyList <IReadOnlyList <DrawCompetitor> > > GroupAsync(Distance distance, IEnumerable <Guid> distanceCombinations, int round,
                                                                                        DistanceDrawSettings settings,
                                                                                        params IHistoricalTimeSelector[] selectors)
        {
            if (distance == null)
            {
                throw new ArgumentNullException(nameof(distance));
            }
            if (distanceCombinations == null)
            {
                throw new ArgumentNullException(nameof(distanceCombinations));
            }
            if (round < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(round));
            }

            Debug.Assert(distance.Competition != null);

            var distanceExpert = distanceExpertManager.Find(distance.Discipline);

            if (distanceExpert == null)
            {
                throw new InvalidDisciplineException();
            }

            var confirmedCompetitors = ConfirmedCompetitors(distance, distanceCombinations, round);
            var roundCompetitors     = await distanceExpert.SelectCompetitorsForRound(distance, round, confirmedCompetitors).ToListAsync();

            var drawCompetitors = new List <DrawCompetitor>();

            switch (settings.GroupMode)
            {
            case DistanceDrawGroupMode.Category:
                drawCompetitors.AddRange(roundCompetitors.Select(rc => new DrawCompetitor(rc, null)));
                break;

            case DistanceDrawGroupMode.Time:
                foreach (var competitor in roundCompetitors)
                {
                    var personCompetitor    = competitor as PersonCompetitor;
                    IPersonLicenseTime time = null;
                    if (personCompetitor != null)
                    {
                        time = await personTimesWorkflow.FindHistoricalTimeAsync(distance.Competition.LicenseIssuerId, distance.Competition.Discipline, distance.Discipline, distance.Value, competitor.LicenseKey, selectors);
                    }
                    drawCompetitors.Add(new DrawCompetitor(competitor, time));
                }
                break;
            }

            var categories = await context.PersonCategories
                             .Where(c => c.LicenseIssuerId == distance.Competition.LicenseIssuerId && c.Discipline == distance.Competition.Discipline).ToListAsync();

            var sortedDrawCompetitors = distanceExpert.SortDrawCompetitors(distance, drawCompetitors, settings, categories).ToList();

            return(distanceExpert.GroupDrawCompetitors(distance, round, sortedDrawCompetitors, settings));
        }
 public async Task UpdateSettingsAsync(DistanceDrawSettings settings)
 {
     await context.SaveChangesAsync();
 }
        public async Task <IReadOnlyDictionary <int, IReadOnlyCollection <Race> > > DrawAsync(Distance distance, IReadOnlyCollection <Guid> distanceCombinations, int round, IReadOnlyList <IReadOnlyList <Guid> > groups, DistanceDrawSettings settings)
        {
            if (distance == null)
            {
                throw new ArgumentNullException(nameof(distance));
            }
            if (round < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(round));
            }

            Debug.Assert(distance.Competition != null);

            var distanceExpert = distanceExpertManager.Find(distance.Discipline);

            if (distanceExpert == null)
            {
                throw new InvalidDisciplineException();
            }

            using (var transaction = context.BeginTransaction(IsolationLevel.RepeatableRead))
                try
                {
                    if (settings.DeleteExisting)
                    {
                        await DeleteRacesAsync(distance, round);
                    }

                    var confirmedCompetitors = ConfirmedCompetitors(distance, distanceCombinations, round);
                    var roundCompetitors     = await distanceExpert.SelectCompetitorsForRound(distance, round, confirmedCompetitors).ToDictionaryAsync(c => c.Id);

                    var competitorGroups = new List <IReadOnlyList <CompetitorBase> >();
                    foreach (var group in groups)
                    {
                        var competitors = new List <CompetitorBase>();
                        foreach (var competitorId in group)
                        {
                            CompetitorBase competitor;
                            if (!roundCompetitors.TryGetValue(competitorId, out competitor))
                            {
                                throw new CompetitorNotFoundException();
                            }

                            competitors.Add(competitor);
                        }

                        await distanceExpert.DrawCompetitorGroupAsync(distance, distanceCombinations, round, competitors, context, settings);

                        competitorGroups.Add(competitors.AsReadOnly());
                    }

                    await distancesWorkflow.ResetFirstHeatAsync(distance, distance.ContinuousNumbering, !distance.ContinuousNumbering
                                                                ?distance.FirstHeat
                                                                : new int?());

                    var races = await distanceExpert.FillCompetitorsInHeatsAsync(distance, distanceCombinations, round, competitorGroups, context, settings);

                    foreach (var heat in races.Keys)
                    {
                        await distancesWorkflow.AddRacesToHeatAsync(distance, round, heat, true, races[heat].ToArray());
                    }

                    await context.SaveChangesAsync();

                    transaction.Commit();

                    return(races);
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
        }
 public abstract Task <IReadOnlyDictionary <int, IReadOnlyCollection <Race> > > FillCompetitorsInHeatsAsync(Distance distance, IReadOnlyCollection <Guid> distanceCombinations, int round, IReadOnlyList <IReadOnlyList <CompetitorBase> > competitorGroups, ICompetitionContext context, DistanceDrawSettings settings);
 public virtual Task DrawCompetitorGroupAsync(Distance distance, IReadOnlyCollection <Guid> distanceCombinations, int round, IList <CompetitorBase> competitors, ICompetitionContext context, DistanceDrawSettings settings)
 {
     throw new DrawModeNotSupportedException();
 }
        public virtual IReadOnlyList <IReadOnlyList <DrawCompetitor> > GroupDrawCompetitors(Distance distance, int round, IReadOnlyList <DrawCompetitor> competitors,
                                                                                            DistanceDrawSettings settings)
        {
            var groups = new List <IReadOnlyList <DrawCompetitor> >();

            switch (settings.GroupMode)
            {
            case DistanceDrawGroupMode.Category:
                groups.AddRange(competitors.GroupBy(c => c.Competitor.Category.Substring(0, settings.CategoryLength)).Select(g => g.ToList()));
                break;

            case DistanceDrawGroupMode.Time:
                var count = 0;
                while (count < competitors.Count)
                {
                    var group = competitors.Skip(count).Take(settings.GroupSize).ToList().AsReadOnly();
                    groups.Add(@group);
                    count += @group.Count;
                }
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
            return(groups.AsReadOnly());
        }
 public virtual IReadOnlyList <DrawCompetitor> SortDrawCompetitors(Distance distance, IEnumerable <DrawCompetitor> competitors, DistanceDrawSettings settings,
                                                                   IReadOnlyList <PersonCategory> categories)
 {
     return(competitors.ToList().AsReadOnly());
 }
Esempio n. 12
0
        public override async Task <IReadOnlyDictionary <int, IReadOnlyCollection <Race> > > FillCompetitorsInHeatsAsync(Distance distance,
                                                                                                                         IReadOnlyCollection <Guid> distanceCombinations, int round, IReadOnlyList <IReadOnlyList <CompetitorBase> > competitorGroups, ICompetitionContext context,
                                                                                                                         DistanceDrawSettings settings)
        {
            var competitors = competitorGroups.SelectMany(g => g).ToList();

            if (!settings.ReverseGroups)
            {
                competitors.Reverse();
            }

            var pairCount   = (competitors.Count + 1) / 2;
            var hasFillPair = distance.StartMode == DistanceStartMode.MultipleHeats && (pairCount % 2) == 1;

            if (hasFillPair)
            {
                pairCount++;
            }

            var firstHeat = distance.Races.Max(r => new int?(r.Heat)) + 1 ?? distance.FirstHeat;

            switch (settings.Mode)
            {
            case DistanceDrawMode.Random:
                return(FillHeatsByCompetitorsOrder(firstHeat, pairCount, hasFillPair, competitors, settings.ReverseFilling, settings.Spreading));

            case DistanceDrawMode.SwitchLanesOrRandom:
                if (distanceCombinations.Count != 1)
                {
                    throw new DrawModeNotSupportedException();
                }

                var distanceCombinationId = distanceCombinations.Single();
                var previousDistance      = await(from d in context.Distances
                                                  where d.CompetitionId == distance.CompetitionId && d.Number < distance.Number &&
                                                  d.Combinations.Any(dc => dc.Id == distanceCombinationId)
                                                  orderby d.Number descending
                                                  select new
                {
                    d.Id,
                    FirstPair = d.FirstHeat
                }).FirstOrDefaultAsync();
                if (previousDistance == null)
                {
                    return(FillHeatsByCompetitorsOrder(firstHeat, pairCount, hasFillPair, competitors, settings.ReverseFilling, settings.Spreading));
                }

                var competitorLookup = competitors.ToDictionary(c => c.Id);
                var previousPairs    = await(from r in context.Races
                                             where r.DistanceId == previousDistance.Id
                                             group r by r.Heat
                                             into heat
                                             select new
                {
                    Pair  = heat.Key,
                    Races = from r in heat
                            select new
                    {
                        r.Lane,
                        r.CompetitorId
                    }
                }).ToListAsync();

                var seed = previousPairs.ToDictionary(p => p.Pair - previousDistance.FirstPair + firstHeat,
                                                      p => p.Races.Where(r => competitorLookup.ContainsKey(r.CompetitorId)).ToDictionary(r => (r.Lane + 1) % 2, r => competitorLookup[r.CompetitorId]));

                return(FillHeatsByFixedLanes(firstHeat, pairCount, seed));

            default:
                throw new DrawModeNotSupportedException();
            }
        }
Esempio n. 13
0
        public override IReadOnlyList <DrawCompetitor> SortDrawCompetitors(Distance distance, IEnumerable <DrawCompetitor> competitors, DistanceDrawSettings settings,
                                                                           IReadOnlyList <PersonCategory> categories)
        {
            switch (settings.GroupMode)
            {
            case DistanceDrawGroupMode.Category:
                return(competitors.OrderByDescending(c => categories.FirstOrDefault(ca => ca.Code == c.Competitor.Category)?.FromAge ?? int.MaxValue)
                       .ThenByDescending(c => c.Competitor.Category.Substring(0, 1))
                       .ToList()
                       .AsReadOnly());

            case DistanceDrawGroupMode.Time:
                return(competitors.OrderBy(c => c.Time?.Time ?? TimeSpan.MaxValue).ToList().AsReadOnly());

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Esempio n. 14
0
 public override Task <IReadOnlyDictionary <int, IReadOnlyCollection <Race> > > FillCompetitorsInHeatsAsync(Distance distance,
                                                                                                            IReadOnlyCollection <Guid> distanceCombinations, int round, IReadOnlyList <IReadOnlyList <CompetitorBase> > competitorGroups, ICompetitionContext context,
                                                                                                            DistanceDrawSettings settings)
 {
     throw new DrawModeNotSupportedException();
 }