public async Task UpdateAsync(DistancePointsTable table, params DistancePoints[] points)
        {
            using (var transaction = context.BeginTransaction(IsolationLevel.Serializable))
                try
                {
                    foreach (var p in table.Points.ToList())
                    {
                        context.DistancePoints.Remove(p);
                    }
                    await context.SaveChangesAsync();

                    foreach (var p in points)
                    {
                        table.Points.Add(p);
                    }
                    await context.SaveChangesAsync();

                    transaction.Commit();
                }
                catch (Exception)
                {
                    transaction.Rollback();
                    throw;
                }
        }
Beispiel #2
0
        public async Task PresentInstanceResultAsync(Race race, string instanceName)
        {
            Debug.Assert(race.Distance != null, "race.Distance != null");

            using (var transaction = context.BeginTransaction(IsolationLevel.RepeatableRead))
                try
                {
                    race.PresentedInstanceName = instanceName;
                    await context.SaveChangesAsync();

                    foreach (var combination in await DistanceCombinations(race.Distance.CompetitionId, race.DistanceId).ToListAsync())
                    {
                        recorder.RecordEvent(new DistanceCombinationClassificationChangedEvent(combination));
                    }

                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
        }
        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 async Task <IReadOnlyCollection <Race> > UpdateRacesInHeatAsync(Distance distance, int round, int heat, params Race[] races)
        {
            using (var transaction = context.BeginTransaction(IsolationLevel.RepeatableRead))
                try
                {
                    var existingRaces = await(from r in context.Races.Include(r => r.Transponders)
                                              where r.DistanceId == distance.Id && r.Round == round && r.Heat == heat
                                              select r).ToListAsync();
                    var removedRaces = new List <Race>();

                    var newLaneRaces         = races.ToDictionary(r => r.Lane);
                    var existingLaneRaces    = existingRaces.ToDictionary(r => r.Lane);
                    var existingTransponders = existingRaces.SelectMany(r => r.Transponders).ToLookup(t => t.Race.CompetitorId);
                    var maxLane = existingLaneRaces.Keys.Union(newLaneRaces.Keys).Select(l => new int?(l)).Max();
                    for (var lane = 0; lane <= maxLane; lane++)
                    {
                        Race newRace;
                        newLaneRaces.TryGetValue(lane, out newRace);
                        Race existingRace;
                        existingLaneRaces.TryGetValue(lane, out existingRace);

                        if (existingRace != null && newRace != null && existingRace.CompetitorId == newRace.Competitor.Id)
                        {
                            continue;
                        }

                        if (existingRace != null)
                        {
                            context.Races.Remove(existingRace);
                            await context.SaveChangesAsync();

                            existingLaneRaces.Remove(lane);
                            removedRaces.Add(existingRace);
                        }

                        if (newRace != null)
                        {
                            newRace.Id           = Guid.NewGuid();
                            newRace.Distance     = distance;
                            newRace.Round        = round;
                            newRace.Heat         = heat;
                            newRace.Transponders = new List <RaceTransponder>();
                            foreach (var transponder in existingTransponders[newRace.Competitor.Id])
                            {
                                newRace.Transponders.Add(new RaceTransponder
                                {
                                    Type     = transponder.Type,
                                    Code     = transponder.Code,
                                    Set      = transponder.Set,
                                    PersonId = transponder.PersonId
                                });
                            }

                            await OnAddingRaceAsync(distance, newRace);

                            context.Races.Add(newRace);
                            await context.SaveChangesAsync();

                            existingLaneRaces[lane] = newRace;
                        }
                    }

                    await context.SaveChangesAsync();

                    recorder.RecordEvent(new DistanceRacesDeletedEvent(distance, removedRaces));
                    recorder.RecordEvent(new DistanceRacesAddedEvent(distance, existingLaneRaces.Values));
                    foreach (var combination in await DistanceCombinations(distance.CompetitionId, distance.Id).ToListAsync())
                    {
                        recorder.RecordEvent(new DistanceCombinationClassificationChangedEvent(combination));
                    }

                    transaction.Commit();
                    return(existingLaneRaces.Values.ToList());
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
        }
        public async Task UpdateCompetitorAsync(Guid competitionId, Guid competitorId, IReadOnlyCollection <DistanceCombinationCompetitor> competitorCombinations)
        {
            using (var transaction = context.BeginTransaction(IsolationLevel.RepeatableRead))
                try
                {
                    var competitor = await context.Competitors.FirstOrDefaultAsync(c => c.Id == competitorId);

                    if (competitor == null)
                    {
                        throw new CompetitorNotFoundException();
                    }

                    foreach (var combination in await Combinations(competitionId, competitorId).ToListAsync())
                    {
                        context.DistanceCombinationCompetitors.Remove(combination);
                    }

                    var combinations = (from c in competitorCombinations
                                        join dc in await Combinations(competitionId).ToListAsync() on c.DistanceCombinationId equals dc.Id
                                        select new
                    {
                        Competitor = c,
                        Combination = dc
                    }).ToList();

                    foreach (var c in combinations)
                    {
                        CategoryFilter.EnsureMatch(c.Combination.CategoryFilter, competitor.Category);
                        ClassFilter.EnsureMatch(c.Combination.ClassFilter, competitor.Class);

                        c.Competitor.Competitor = competitor;
                        context.DistanceCombinationCompetitors.Add(c.Competitor);

                        if (c.Competitor.Status == DistanceCombinationCompetitorStatus.Withdrawn)
                        {
                            var competitorRaces = await(from r in context.Races
                                                        where r.Distance.Combinations.Any(dc => dc.Id == c.Combination.Id) && r.CompetitorId == c.Competitor.CompetitorId
                                                        select r).ToListAsync();
                            foreach (var race in competitorRaces)
                            {
                                context.Races.Remove(race);
                            }
                        }
                    }

                    if (competitorCombinations.Any(cc => cc.Status == DistanceCombinationCompetitorStatus.Confirmed || cc.Status == DistanceCombinationCompetitorStatus.Withdrawn))
                    {
                        competitor.Status = CompetitorStatus.Confirmed;
                    }
                    else if (competitorCombinations.All(cc => cc.Status == DistanceCombinationCompetitorStatus.Pending))
                    {
                        competitor.Status = CompetitorStatus.Pending;
                    }

                    await context.SaveChangesAsync();

                    foreach (var combination in combinations.Select(c => c.Combination))
                    {
                        recorder.RecordEvent(new DistanceCombinationClassificationChangedEvent(combination));
                    }

                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
        }
        public async Task <Competition> CloneCompetitionAsync(Competition current, CompetitionCloneSettings settings)
        {
            using (var transaction = context.BeginTransaction(IsolationLevel.RepeatableRead))
                try
                {
                    var shift = settings.Starts - current.Starts;
                    var clone = new Competition
                    {
                        SerieId         = settings.CloneSerie ? current.SerieId : new Guid?(),
                        VenueCode       = settings.CloneVenue ? current.VenueCode : null,
                        Discipline      = current.Discipline,
                        Location        = current.Location,
                        LocationFlags   = current.LocationFlags,
                        Extra           = current.Extra,
                        Sponsor         = current.Sponsor,
                        Name            = settings.Name ?? current.Name,
                        Class           = current.Class,
                        LicenseIssuerId = current.LicenseIssuerId,
                        Starts          = settings.Starts,
                        Ends            = current.Ends + shift,
                        TimeZone        = current.TimeZone,
                        Culture         = current.Culture
                    };
                    await AddCompetitionAsync(clone);

                    var clonedDistances = new Dictionary <Guid, Distance>();
                    if (settings.CloneDistances)
                    {
                        foreach (var currentDistance in await DistancesWorkflow.Distances(current.Id).ToListAsync())
                        {
                            var clonedDistance = await DistancesWorkflow.CloneDistanceAsync(currentDistance, settings.DistanceCloneSettings, settings.CloneVenue, clone.Id,
                                                                                            shift);

                            clonedDistances.Add(currentDistance.Id, clonedDistance);
                        }
                    }

                    if (settings.CloneDistanceCombinations)
                    {
                        foreach (var currentDistanceCombination in await DistanceCombinationsWorkflow.Combinations(current.Id).Include(c => c.Distances).ToListAsync())
                        {
                            var clonedDistanceCombination =
                                await
                                DistanceCombinationsWorkflow.CloneDistanceCombinationAsync(currentDistanceCombination, settings.DistanceCombinationCloneSettings, clone.Id,
                                                                                           shift);

                            if (settings.CloneDistances)
                            {
                                clonedDistanceCombination.Distances = new Collection <Distance>();
                                await
                                DistanceCombinationsWorkflow.UpdateCombinationDistancesAsync(clonedDistanceCombination,
                                                                                             currentDistanceCombination.Distances.Select(d => clonedDistances[d.Id].Id).ToArray());
                            }
                        }
                    }

                    transaction.Commit();
                    return(clone);
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
        }