Skip to content

Commit

Permalink
Update MatchPlanner
Browse files Browse the repository at this point in the history
* 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)
  • Loading branch information
axunonb committed Aug 24, 2023
1 parent e6a236a commit c2e475e
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ public enum ClearMatchDates
OnlyAutoGenerated = 0x01,
OnlyManual = 0x02,
All = 0x03
}
}
41 changes: 27 additions & 14 deletions TournamentManager/TournamentManager/Plan/MatchPlanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
namespace TournamentManager.Plan;

/// <summary>
/// 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.
/// </summary>
public class MatchPlanner
{
Expand Down Expand Up @@ -46,8 +47,6 @@ private async Task LoadEntitiesAsync(CancellationToken cancellationToken)
AreEntitiesLoaded = true;
}

public List<long> TeamsWithoutHomeMatches { get; } = new();

/// <summary>
/// Generates dates which are excluded for the tournament with <see cref="TournamentContext.MatchPlanTournamentId"/>
/// and saves them to persistent storage. Existing entries for the tournament are removed.
Expand All @@ -57,14 +56,12 @@ private async Task LoadEntitiesAsync(CancellationToken cancellationToken)
/// <returns></returns>
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 ==
Expand Down Expand Up @@ -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.");

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -334,7 +333,7 @@ private static List<DateTime> GetOccupiedMatchDates(TeamCombination<long> 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);
}
Expand Down Expand Up @@ -382,4 +381,18 @@ private void AssignRoundDatePeriods(RoundLegEntity roundLeg,
index++;
}
}

/// <summary>
/// Gets teams IDs for the <param name="round"></param> where no home venue or no home match time set for a team.
/// </summary>
private static IEnumerable<long> GetTeamsWithoutHomeMatches(RoundEntity round)
{
foreach (var team in round.TeamCollectionViaTeamInRound)
{
if (team.VenueId == null || team.MatchTime == null || team.MatchDayOfWeek == null)
{
yield return team.Id;
}
}
}
}

0 comments on commit c2e475e

Please sign in to comment.