From c2e475ecb43af15588f57efee9f90605cf95e288 Mon Sep 17 00:00:00 2001 From: axunonb Date: Fri, 25 Aug 2023 00:17:50 +0200 Subject: [PATCH] Update MatchPlanner * MatchPlanner.GenerateFixturesForRound(...) creates only away fixtures for teams without home venue or home match time * MatchPlanner.GenerateExcludedDates(...) now loads only required data from database (e.g. no team entities) --- ...mClearMatchDates.cs => ClearMatchDates.cs} | 2 +- .../TournamentManager/Plan/MatchPlanner.cs | 41 ++++++++++++------- 2 files changed, 28 insertions(+), 15 deletions(-) rename TournamentManager/TournamentManager/Plan/{enumClearMatchDates.cs => ClearMatchDates.cs} (98%) diff --git a/TournamentManager/TournamentManager/Plan/enumClearMatchDates.cs b/TournamentManager/TournamentManager/Plan/ClearMatchDates.cs similarity index 98% rename from TournamentManager/TournamentManager/Plan/enumClearMatchDates.cs rename to TournamentManager/TournamentManager/Plan/ClearMatchDates.cs index edf7f4fc..4a04675f 100644 --- a/TournamentManager/TournamentManager/Plan/enumClearMatchDates.cs +++ b/TournamentManager/TournamentManager/Plan/ClearMatchDates.cs @@ -7,4 +7,4 @@ public enum ClearMatchDates OnlyAutoGenerated = 0x01, OnlyManual = 0x02, All = 0x03 -} \ No newline at end of file +} diff --git a/TournamentManager/TournamentManager/Plan/MatchPlanner.cs b/TournamentManager/TournamentManager/Plan/MatchPlanner.cs index 24437532..8529745a 100644 --- a/TournamentManager/TournamentManager/Plan/MatchPlanner.cs +++ b/TournamentManager/TournamentManager/Plan/MatchPlanner.cs @@ -8,7 +8,8 @@ namespace TournamentManager.Plan; /// -/// Generates matches for a tournament or round. +/// Generates fixtures for all teams of a tournament or round. +/// If the home team has no venue or home match time defined, it will only have away matches. /// public class MatchPlanner { @@ -46,8 +47,6 @@ private async Task LoadEntitiesAsync(CancellationToken cancellationToken) AreEntitiesLoaded = true; } - public List TeamsWithoutHomeMatches { get; } = new(); - /// /// Generates dates which are excluded for the tournament with /// and saves them to persistent storage. Existing entries for the tournament are removed. @@ -57,14 +56,12 @@ private async Task LoadEntitiesAsync(CancellationToken cancellationToken) /// public async Task GenerateExcludedDates(string excelImportFile, CancellationToken cancellationToken) { - if (!AreEntitiesLoaded) await LoadEntitiesAsync(cancellationToken); - - var allRoundLegs = await _appDb.RoundRepository.GetRoundLegPeriodAsync( - new PredicateExpression(RoundLegPeriodFields.TournamentId == - _tenantContext.TournamentContext.MatchPlanTournamentId), cancellationToken); + var roundLegPeriods = await _appDb.RoundRepository.GetRoundLegPeriodAsync(new PredicateExpression( + RoundLegPeriodFields.TournamentId == _tenantContext.TournamentContext.MatchPlanTournamentId), + cancellationToken); - var minDate = allRoundLegs.Min(leg => leg.StartDateTime); - var maxDate = allRoundLegs.Max(leg => leg.EndDateTime); + var minDate = roundLegPeriods.Min(leg => leg.StartDateTime); + var maxDate = roundLegPeriods.Max(leg => leg.EndDateTime); // remove all existing excluded dates for the tournament var filter = new RelationPredicateBucket(ExcludeMatchDateFields.TournamentId == @@ -118,8 +115,6 @@ public async Task GenerateFixturesForRound(RoundEntity round, bool keepExisting, { if (!AreEntitiesLoaded) await LoadEntitiesAsync(cancellationToken); - round = _tournament.Rounds.First(r => r.Id == round.Id); - if (_appDb.MatchRepository.AnyCompleteMatchesExist(round)) throw new InvalidOperationException($"Completed matches exist for round '{round.Id}'. Generating fixtures aborted."); @@ -157,10 +152,14 @@ await _appDb.GenericRepository.DeleteEntitiesDirectlyAsync(typeof(MatchEntity), /* * Special treatment for teams which do not have home matches */ + var teamsWithoutHomeMatches = GetTeamsWithoutHomeMatches(round).ToList(); + foreach (var teamCombinationGroup in bundledGroups) foreach (var combination in teamCombinationGroup) { - if (!TeamsWithoutHomeMatches.Contains(combination.HomeTeam)) continue; + if (!teamsWithoutHomeMatches.Contains(combination.HomeTeam)) continue; + + _logger.LogDebug("Team cannot have home matches - {TeamId}", combination.HomeTeam); // swap home and guest team, keep referee unchanged (combination.HomeTeam, combination.GuestTeam) = (combination.GuestTeam, combination.HomeTeam); @@ -334,7 +333,7 @@ private static List GetOccupiedMatchDates(TeamCombination combin if (i + 1 >= matchDates.Count - 1) { bestDate = matchDates[^1].Where(md => md.MinTimeDiff == matchDates[^1].Min(d => d.MinTimeDiff)) - .OrderBy(md => md.MinTimeDiff).FirstOrDefault(); + .MinBy(md => md.MinTimeDiff); // the last "j-increment" is always the same as "matchDates[^1]" (loop condition) matchDatePerCombination.Add(bestDate); } @@ -382,4 +381,18 @@ private void AssignRoundDatePeriods(RoundLegEntity roundLeg, index++; } } + + /// + /// Gets teams IDs for the where no home venue or no home match time set for a team. + /// + private static IEnumerable GetTeamsWithoutHomeMatches(RoundEntity round) + { + foreach (var team in round.TeamCollectionViaTeamInRound) + { + if (team.VenueId == null || team.MatchTime == null || team.MatchDayOfWeek == null) + { + yield return team.Id; + } + } + } }