Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update MatchPlanner #105

Merged
merged 1 commit into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}
}
}
}