internal void GenerateNew(RoundEntity round) { var teamIdProcessed = new List <long>(); var listTeamsWithSameVenue = new List <EntityCollection <TeamEntity> >(); // Make a list of teams of the same round and with the same venue + weekday + match time // Venues will later be assigned to these teams in an alternating way foreach (var team in round.TeamCollectionViaTeamInRound) { // the collection will contain at least one team EntityCollection <TeamEntity> teams = GetTeamsWithSameVenueAndMatchTime(team, round); if (!teamIdProcessed.Contains(teams[0].Id)) { listTeamsWithSameVenue.Add(teams); foreach (var t in teams) { if (!teamIdProcessed.Contains(t.Id)) { teamIdProcessed.Add(t.Id); } } } } foreach (var roundLeg in round.RoundLegs) { DateTime startDate = roundLeg.StartDateTime; DateTime endDate = roundLeg.EndDateTime; var matchDate = new DateTime(); foreach (var teamsWithSameVenue in listTeamsWithSameVenue) { int teamIndex = 0; // get the first possible match date equal or after the leg's starting date matchDate = IncrementDateUntilDayOfWeek(startDate, (DayOfWeek)teamsWithSameVenue[teamIndex].MatchDayOfWeek); // process the period of a leg while (matchDate <= endDate) { // if there is more than one team per venue with same weekday and match time, // match dates will be assigned alternately TeamEntity team = teamsWithSameVenue[teamIndex]; DateTime matchDateAndTime = DateTime.Parse(string.Concat(matchDate.ToShortDateString(), " ", team.MatchTime)); // check whether the calculated date // is within the borders of round legs (if any) and is not marked as excluded if (IsDateWithinRoundLegDateTime(roundLeg, matchDate) && !IsExcludedDate(matchDate, round.Id, team.Id) && !IsVenueOccupiedByMatch(new DateTimePeriod(matchDateAndTime, matchDateAndTime.Add(_matchPlanner.PlannedDurationOfMatch)), team.VenueId.Value)) { var av = new AvailableMatchDateEntity(); av.TournamentId = _matchPlanner.Tournament.Id; av.HomeTeamId = team.Id; av.VenueId = team.Venue.Id; av.MatchStartTime = matchDateAndTime; av.MatchEndTime = matchDateAndTime.Add(_matchPlanner.PlannedDurationOfMatch); av.IsGenerated = true; av.CreatedOn = DateTime.Now; _availableMatchDate.Add(av); teamIndex = (++teamIndex >= teamsWithSameVenue.Count) ? 0 : teamIndex; } matchDate = matchDate.Date.AddDays(7); } } } // save to the persistent storage _matchPlanner.Adapter.SaveEntityCollection(_availableMatchDate, true, false); }
/// <summary> /// Generate available match dates for teams where /// <see cref="TeamEntity.MatchDayOfWeek"/>, <see cref="TeamEntity.MatchTime"/>, <see cref="TeamEntity.VenueId"/> /// are not <see langword="null"/>. /// </summary> /// <param name="round"></param> /// <param name="cancellationToken"></param> /// <returns></returns> internal async Task GenerateNewAsync(RoundEntity round, CancellationToken cancellationToken) { await Initialize(cancellationToken); var teamIdProcessed = new List <long>(); var listTeamsWithSameVenue = new List <EntityCollection <TeamEntity> >(); // Make a list of teams of the same round and with the same venue AND weekday AND match time // Venues will later be assigned to these teams alternately foreach (var team in round.TeamCollectionViaTeamInRound) { // the collection will contain at least one team var teams = GetTeamsWithSameVenueAndMatchTime(team, round); if (teamIdProcessed.Contains(teams[0].Id)) { continue; } listTeamsWithSameVenue.Add(teams); foreach (var t in teams) { if (!teamIdProcessed.Contains(t.Id)) { teamIdProcessed.Add(t.Id); } } } foreach (var roundLeg in round.RoundLegs) { var startDate = DateTime.SpecifyKind(roundLeg.StartDateTime, DateTimeKind.Utc); var endDate = DateTime.SpecifyKind(roundLeg.EndDateTime, DateTimeKind.Utc); foreach (var teamsWithSameVenue in listTeamsWithSameVenue) { var teamIndex = 0; // Make sure these values are not null if (!teamsWithSameVenue[teamIndex].MatchDayOfWeek.HasValue || !teamsWithSameVenue[teamIndex].MatchTime.HasValue || !teamsWithSameVenue[teamIndex].VenueId.HasValue) { continue; } // Create Tuple for non-nullable context var team = (Id : teamsWithSameVenue[teamIndex].Id, MatchDayOfWeek : (DayOfWeek)teamsWithSameVenue[teamIndex].MatchDayOfWeek !.Value, MatchTime : teamsWithSameVenue[teamIndex].MatchTime !.Value, VenueId : teamsWithSameVenue[teamIndex].VenueId !.Value); // get the first possible match date equal or after the leg's starting date var matchDate = IncrementDateUntilDayOfWeek(startDate, team.MatchDayOfWeek); // process the period of a leg while (matchDate <= endDate) { // if there is more than one team per venue with same weekday and match time, // match dates will be assigned alternately var matchDateAndTimeUtc = _timeZoneConverter.ToUtc(matchDate.Date.Add(team.MatchTime)); // check whether the calculated date // is within the borders of round legs (if any) and is not marked as excluded if (IsDateWithinRoundLegDateTime(roundLeg, matchDateAndTimeUtc) && !IsExcludedDate(matchDateAndTimeUtc, round.Id, team.Id) && !await IsVenueOccupiedByMatchAsync( new DateTimePeriod(matchDateAndTimeUtc, matchDateAndTimeUtc.Add(_tenantContext.TournamentContext.FixtureRuleSet .PlannedDurationOfMatch)), team.VenueId, cancellationToken)) { var av = new AvailableMatchDateEntity { TournamentId = _tenantContext.TournamentContext.MatchPlanTournamentId, HomeTeamId = team.Id, VenueId = team.VenueId, MatchStartTime = matchDateAndTimeUtc, MatchEndTime = matchDateAndTimeUtc.Add(_tenantContext.TournamentContext.FixtureRuleSet.PlannedDurationOfMatch), IsGenerated = true }; _generatedAvailableMatchDateEntities.Add(av); teamIndex = ++teamIndex >= teamsWithSameVenue.Count ? 0 : teamIndex; } matchDate = matchDate.Date.AddDays(7); } } } _logger.LogTrace("Generated {Count} UTC dates for HomeTeams:", _generatedAvailableMatchDateEntities.Count); _logger.LogTrace("{Generated}\n", _generatedAvailableMatchDateEntities.Select(gen => (gen.HomeTeamId, gen.MatchStartTime))); // save to the persistent storage // await _appDb.GenericRepository.SaveEntitiesAsync(_generatedAvailableMatchDateEntities, true, false, cancellationToken); }