Skip to content

Commit

Permalink
Refactor scheduling of fixtures in namespace TournamentManager.Plan (#…
Browse files Browse the repository at this point in the history
…131)

* Initial commit

* Changing internal components in TournamentManager
* Implement new round-robin classes
* Seprate MatchCreater and MatchScheduler

* Continue refactoring

* IRoundRobinSystem type parameters are IEquatable struct
* Add logging to ExcludeMatchDates
* Add RefereeAssigner classes
* MatchCreator type parameters are IEquatable struct
* ParticipantCombination type parameters are IEquatable struct
* Refactor MatchCreator and MatchScheduler
* MatchScheduler will sets the planned date / time to null, if no available date within a target period can be found
* Add more unit tests

* Add RefereeType to new TournamentContext.RefereeRuleSet

* Improve performance for creating fixtures with MatchScheduler

* Planned matches of a tournament are cached for faster checks of available dates
* Extend debug logging
* Update tenant settings for development to include RefereeRuleSet

Update MatchScheduler

* Add MatchEntityListExtensions

* Add ability to find next and previous matches in the list
* Add unit tests

* MatchScheduler: Make the time periods of turns consecutive without gaps

Adjust time periods for turns in the round so that the start date of the next turn is the end date of the previous turn plus 1 day.

* Replace AppDb references with IAppDb

* Add 2nd trial if MatchScheduler can't find available match dates

* Add unit tests for AvailableMatchDates

* Change MatchRepository.GetMatches(...) to async

* Change TournamentCreator and MatchScheduler to use async database queries

* Add OnBeforeSave and OnAfterSave events to MatchScheduler

* Add unit tests for MatchScheduler (91% coverage)
  • Loading branch information
axunonb authored Jan 24, 2024
1 parent 8e67f14 commit 5b1b74d
Show file tree
Hide file tree
Showing 77 changed files with 3,248 additions and 1,096 deletions.
5 changes: 5 additions & 0 deletions League.Demo/Configuration/Tenant.Default.Development.config
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,10 @@
<MustBeSet>True</MustBeSet>
</HomeVenue>
</TeamRuleSet>
<!-- Rules for referee master data -->
<RefereeRuleSet>
<!-- Rules for organizing referees -->
<RefereeType>None</RefereeType>
</RefereeRuleSet>
</TournamentContext>
</TenantContext>
5 changes: 5 additions & 0 deletions League.Demo/Configuration/Tenant.Default.Production.config
Original file line number Diff line number Diff line change
Expand Up @@ -168,5 +168,10 @@
<MustBeSet>True</MustBeSet>
</HomeVenue>
</TeamRuleSet>
<!-- Rules for referee master data -->
<RefereeRuleSet>
<!-- Rules for organizing referees -->
<RefereeType>None</RefereeType>
</RefereeRuleSet>
</TournamentContext>
</TenantContext>
5 changes: 5 additions & 0 deletions League.Demo/Configuration/Tenant.OtherOrg.Development.config
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,10 @@
<MustBeSet>True</MustBeSet>
</HomeVenue>
</TeamRuleSet>
<!-- Rules for referee master data -->
<RefereeRuleSet>
<!-- Rules for organizing referees -->
<RefereeType>Home</RefereeType>
</RefereeRuleSet>
</TournamentContext>
</TenantContext>
5 changes: 5 additions & 0 deletions League.Demo/Configuration/Tenant.OtherOrg.Production.config
Original file line number Diff line number Diff line change
Expand Up @@ -168,5 +168,10 @@
<MustBeSet>True</MustBeSet>
</HomeVenue>
</TeamRuleSet>
<!-- Rules for referee master data -->
<RefereeRuleSet>
<!-- Rules for organizing referees -->
<RefereeType>Home</RefereeType>
</RefereeRuleSet>
</TournamentContext>
</TenantContext>
5 changes: 5 additions & 0 deletions League.Demo/Configuration/Tenant.TestOrg.Development.config
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,10 @@
<MustBeSet>True</MustBeSet>
</HomeVenue>
</TeamRuleSet>
<!-- Rules for referee master data -->
<RefereeRuleSet>
<!-- Rules for organizing referees -->
<RefereeType>Home</RefereeType>
</RefereeRuleSet>
</TournamentContext>
</TenantContext>
5 changes: 5 additions & 0 deletions League.Demo/Configuration/Tenant.TestOrg.Production.config
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,10 @@
<MustBeSet>True</MustBeSet>
</HomeVenue>
</TeamRuleSet>
<!-- Rules for referee master data -->
<RefereeRuleSet>
<!-- Rules for organizing referees -->
<RefereeType>Home</RefereeType>
</RefereeRuleSet>
</TournamentContext>
</TenantContext>
2 changes: 1 addition & 1 deletion League.Tests/Identity/RoleStoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace League.Tests.Identity;
public class RoleStoreTests
{
private readonly UnitTestHelpers _uth = new();
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private readonly RoleStore _roleStore;
private readonly UserStore _userStore;

Expand Down
2 changes: 1 addition & 1 deletion League.Tests/Identity/UserAuthenticationTokenStoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace League.Tests.Identity;
public class UserAuthenticationTokenStoreTests
{
private readonly UnitTestHelpers _uth = new();
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private readonly UserStore _store;

public UserAuthenticationTokenStoreTests()
Expand Down
2 changes: 1 addition & 1 deletion League.Tests/Identity/UserClaimStoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace League.Tests.Identity;
public class UserClaimStoreTests
{
private readonly UnitTestHelpers _uth = new();
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private ApplicationUser _user = new();
private readonly UserStore _store;
private TeamEntity _team = new();
Expand Down
2 changes: 1 addition & 1 deletion League.Tests/Identity/UserLoginStoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace League.Tests.Identity;
public class UserLoginStoreTests
{
private readonly UnitTestHelpers _uth = new();
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private readonly UserStore _store;

public UserLoginStoreTests()
Expand Down
2 changes: 1 addition & 1 deletion League.Tests/Identity/UserRoleStoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace League.Tests.Identity;
public class UserRoleStoreTests
{
private readonly UnitTestHelpers _uth = new();
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private readonly UserStore _userStore;
private ApplicationUser _user = new();

Expand Down
2 changes: 1 addition & 1 deletion League.Tests/Identity/UserStoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace League.Tests.Identity;
public class UserStoreTests
{
private readonly UnitTestHelpers _uth = new();
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private readonly UserStore _store;
private readonly RoleStore _roleStore;

Expand Down
2 changes: 1 addition & 1 deletion League/Components/RoundSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace League.Components;
public class RoundSelector : ViewComponent
{
private readonly ITenantContext _tenantContext;
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private readonly ILogger<RoundSelector> _logger;

public RoundSelector(ITenantContext tenantContext, ILogger<RoundSelector> logger)
Expand Down
2 changes: 1 addition & 1 deletion League/Components/VenueSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace League.Components;

public class VenueSelector : ViewComponent
{
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private readonly ILogger<VenueSelector> _logger;

public VenueSelector(ITenantContext tenantContext, ILogger<VenueSelector> logger)
Expand Down
2 changes: 1 addition & 1 deletion League/Controllers/Contact.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace League.Controllers;
public class Contact : AbstractController
{
#pragma warning disable IDE0052 // Remove unread private members
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private readonly TenantStore _tenantStore;
#pragma warning restore IDE0052 // Remove unread private members
private readonly ITenantContext _tenantContext;
Expand Down
2 changes: 1 addition & 1 deletion League/Controllers/Map.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class Map : AbstractController
private readonly IConfiguration _configuration;
private readonly ILogger<Map> _logger;
private readonly ITenantContext _tenantContext;
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private readonly IStringLocalizer<Map> _localizer;
private readonly GoogleConfiguration _googleConfig;

Expand Down
2 changes: 1 addition & 1 deletion League/Controllers/Match.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace League.Controllers;
public class Match : AbstractController
{
private readonly ITenantContext _tenantContext;
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private readonly IStringLocalizer<Match> _localizer;
private readonly IAuthorizationService _authorizationService;
private readonly Axuno.Tools.DateAndTime.TimeZoneConverter _timeZoneConverter;
Expand Down
2 changes: 1 addition & 1 deletion League/Controllers/Ranking.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class Ranking : AbstractController
{
private readonly ITenantContext _tenantContext;
private readonly IWebHostEnvironment _webHostEnvironment;
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private readonly ILogger<Ranking> _logger;
private readonly IMemoryCache _memoryCache;

Expand Down
2 changes: 1 addition & 1 deletion League/Controllers/Team.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace League.Controllers;
public class Team : AbstractController
{
private readonly ITenantContext _tenantContext;
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private readonly IStringLocalizer<Team> _localizer;
private readonly IAuthorizationService _authorizationService;
private readonly ILogger<Team> _logger;
Expand Down
2 changes: 1 addition & 1 deletion League/Controllers/TeamApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace League.Controllers;
public class TeamApplication : AbstractController
{
private readonly ITenantContext _tenantContext;
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private readonly IAuthorizationService _authorizationService;
private readonly ILogger<TeamApplication> _logger;
private readonly Axuno.Tools.DateAndTime.TimeZoneConverter _timeZoneConverter;
Expand Down
2 changes: 1 addition & 1 deletion League/Controllers/Venue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace League.Controllers;
public class Venue : AbstractController
{
private readonly ITenantContext _tenantContext;
private readonly AppDb _appDb;
private readonly IAppDb _appDb;
private readonly IAuthorizationService _authorizationService;
private readonly IStringLocalizer<Venue> _localizer;
private readonly RegionInfo _regionInfo;
Expand Down
2 changes: 1 addition & 1 deletion League/Identity/RoleStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace League.Identity;
/// </summary>
public class RoleStore : IRoleStore<ApplicationRole>, IRoleClaimStore<ApplicationRole>
{
private readonly TournamentManager.MultiTenancy.AppDb _appDb;
private readonly IAppDb _appDb;
private readonly ILogger<UserStore> _logger;
private readonly ILookupNormalizer _keyNormalizer;
private readonly IdentityErrorDescriber _identityErrorDescriber;
Expand Down
2 changes: 1 addition & 1 deletion League/Identity/UserStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace League.Identity;
/// </summary>
public class UserStore : IUserStore<ApplicationUser>, IUserEmailStore<ApplicationUser>, IUserPhoneNumberStore<ApplicationUser>, IUserPasswordStore<ApplicationUser>, IUserRoleStore<ApplicationUser>, IUserClaimStore<ApplicationUser>, IUserSecurityStampStore<ApplicationUser>, IUserLoginStore<ApplicationUser>, IUserAuthenticationTokenStore<ApplicationUser>, IUserLockoutStore<ApplicationUser>
{
private readonly TournamentManager.MultiTenancy.AppDb _appDb;
private readonly IAppDb _appDb;
private readonly ILogger<UserStore> _logger;
private readonly ILookupNormalizer _keyNormalizer;
private readonly IdentityErrorDescriber _identityErrorDescriber;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using NUnit.Framework;
using FluentAssertions;
using TournamentManager.DAL.EntityClasses;
using TournamentManager.ExtensionMethods;

namespace TournamentManager.Tests.ExtensionMethods;

[TestFixture]
public class MatchEntityListExtensionTests
{
private readonly List<MatchEntity> _matches = new()
{
new MatchEntity {Id = 1, HomeTeamId = 1, GuestTeamId = 2, PlannedStart = DateTime.UtcNow.AddDays(-1), PlannedEnd = DateTime.UtcNow.AddDays(-1).AddHours(2), VenueId = 1},
new MatchEntity {Id = 2, HomeTeamId = 1, GuestTeamId = 3, PlannedStart = DateTime.UtcNow.AddDays(-1), PlannedEnd = DateTime.UtcNow.AddDays(-1).AddHours(2), VenueId = 1},
new MatchEntity {Id = 3, HomeTeamId = 2, GuestTeamId = 3, PlannedStart = DateTime.UtcNow.AddDays(-1), PlannedEnd = DateTime.UtcNow.AddDays(-1).AddHours(2), VenueId = 1},
new MatchEntity {Id = 4, HomeTeamId = 1, GuestTeamId = 4, PlannedStart = DateTime.UtcNow.AddDays(-1), PlannedEnd = DateTime.UtcNow.AddDays(-1).AddHours(2), VenueId = 1},
new MatchEntity {Id = 5, HomeTeamId = 4, GuestTeamId = 2, PlannedStart = DateTime.UtcNow.AddDays(-1), PlannedEnd = DateTime.UtcNow.AddDays(-1).AddHours(2), VenueId = 1},
new MatchEntity {Id = 6, HomeTeamId = 3, GuestTeamId = 4, PlannedStart = DateTime.UtcNow.AddDays(-1), PlannedEnd = DateTime.UtcNow.AddDays(-1).AddHours(2), VenueId = 1},
new MatchEntity {Id = 7, HomeTeamId = 1, GuestTeamId = 5, PlannedStart = DateTime.UtcNow.AddDays(-1), PlannedEnd = DateTime.UtcNow.AddDays(-1).AddHours(2), VenueId = 1},
new MatchEntity {Id = 8, HomeTeamId = 2, GuestTeamId = 5, PlannedStart = DateTime.UtcNow.AddDays(-1), PlannedEnd = DateTime.UtcNow.AddDays(-1).AddHours(2), VenueId = 1},
new MatchEntity {Id = 9, HomeTeamId = 3, GuestTeamId = 5, PlannedStart = DateTime.UtcNow.AddDays(-1), PlannedEnd = DateTime.UtcNow.AddDays(-1).AddHours(2), VenueId = 1},
new MatchEntity {Id = 10, HomeTeamId = 4, GuestTeamId = 5, PlannedStart = DateTime.UtcNow.AddDays(-1), PlannedEnd = DateTime.UtcNow.AddDays(-1).AddHours(2), VenueId = 1},
new MatchEntity {Id = 11, HomeTeamId = 10, GuestTeamId = 11, PlannedStart = null, PlannedEnd = null, VenueId = null},
new MatchEntity {Id = 12, HomeTeamId = 12, GuestTeamId = 10, PlannedStart = null, PlannedEnd = DateTime.UtcNow, VenueId = null},
new MatchEntity {Id = 13, HomeTeamId = 11, GuestTeamId = 13, PlannedStart = DateTime.UtcNow, PlannedEnd = null, VenueId = null}
};

[TestCase(1, -1, 0, false, 0)]
[TestCase(1, -1, 5, false, 3)]
[TestCase(1, 2, 5, false, 5)]
[TestCase(10, 13, 12, false, 0)]
[TestCase(10, 13, 12, true, 2)]
public void Previous_Matches_Relative_To_Index_Should_Be_Found(long team1, long team2, int startIndex, bool includeUndefined, int expected)
{
var teamIds = new[] {team1, team2};
var matches = _matches.GetPreviousMatches(startIndex, teamIds, includeUndefined).ToList();

Assert.That(matches.Count, Is.EqualTo(expected));

}

[TestCase(-1)]
[TestCase(13)]
public void Invalid_StartIndex_For_Previous_Should_Throw(int startIndex)
{
var teamIds = new long[] { 1 };

Assert.That(() => _matches.GetPreviousMatches(startIndex, teamIds, true).ToList(), Throws.TypeOf<ArgumentOutOfRangeException>());
}

[TestCase(1, -1, 12, false, 0)]
[TestCase(1, -1, 0, false, 3)]
[TestCase(1, 2, 1, false, 5)]
[TestCase(10, 13, 0, false, 0)]
[TestCase(10, 13, 0, true, 3)]
public void Next_Matches_Relative_To_Index_Should_Be_Found(long team1, long team2, int startIndex, bool includeUndefined, int expected)
{
var teamIds = new[] { team1, team2 };
var matches = _matches.GetNextMatches(startIndex, teamIds, includeUndefined).ToList();

Assert.That(matches.Count, Is.EqualTo(expected));
}

[TestCase(-1)]
[TestCase(13)]
public void Invalid_StartIndex_For_Next_Should_Throw(int startIndex)
{
var teamIds = new long[] { 1 };

Assert.That(() => _matches.GetNextMatches(startIndex, teamIds, true).ToList(), Throws.TypeOf<ArgumentOutOfRangeException>());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ namespace TournamentManager.Tests.ModelValidators;
public class FixtureValidatorTests
{
private (ITenantContext TenantConext, Axuno.Tools.DateAndTime.TimeZoneConverter TimeZoneConverter, PlannedMatchRow PlannedMatch) _data;
#pragma warning disable IDE0052 // Remove unread private members
private readonly AppDb _appDb; // mocked in CTOR
#pragma warning restore IDE0052 // Remove unread private members
private readonly CultureInfo _culture = CultureInfo.GetCultureInfo("en-US");
private const string ExcludedDateReason = "Unit-Test";

Expand Down Expand Up @@ -122,14 +119,6 @@ public FixtureValidatorTests()
tenantContextMock.SetupDbContext(dbContextMock);
_data.TenantConext = tenantContextMock.Object;

_appDb = appDbMock.Object;

//var teamIds = orgCtxMock.Object.AppDb.MatchRepository.AreTeamsBusyAsync(new MatchEntity {Id = 1, HomeTeamId = 11, GuestTeamId = 22}, false, CancellationToken.None).Result;
//var matchrow = venueRepoMock.Object.GetOccupyingMatchesAsync(1, new DateTimePeriod(null, default(DateTime?)), 2, CancellationToken.None).Result;
//var venue = appDbMock.Object.VenueRepository.GetVenueById(2);
//var isValid = orgCtxMock.Object.AppDb.VenueRepository.IsValidVenueId(22).Result;
//isValid = orgCtxMock.Object.AppDb.VenueRepository.IsValidVenueId(21).Result;

#endregion
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ namespace TournamentManager.Tests.ModelValidators;
public class MatchResultValidatorTests
{
private readonly (ITenantContext TenantContext, Axuno.Tools.DateAndTime.TimeZoneConverter TimeZoneConverter, (MatchRuleEntity matchRule, SetRuleEntity setRule)) _data;
#pragma warning disable IDE0052 // Remove unread private members
private readonly AppDb _appDb; // mocked in CTOR
#pragma warning restore IDE0052 // Remove unread private members

public MatchResultValidatorTests()
{
Expand Down Expand Up @@ -53,8 +50,6 @@ public MatchResultValidatorTests()
);
appDbMock.Setup(a => a.RoundRepository).Returns(roundRepoMock.Object);

_appDb = appDbMock.Object;

var dbContextMock = TestMocks.GetDbContextMock();
dbContextMock.SetupAppDb(appDbMock);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ namespace TournamentManager.Tests.ModelValidators;
public class TeamValidatorTests
{
private readonly ITenantContext _tenantContext;
#pragma warning disable IDE0052 // Remove unread private members
private readonly AppDb _appDb; // mocked in CTOR
#pragma warning restore IDE0052 // Remove unread private members

public TeamValidatorTests()
{
Expand Down Expand Up @@ -54,8 +51,6 @@ public TeamValidatorTests()

_tenantContext = tenantContextMock.Object;

_appDb = appDbMock.Object;

#endregion
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ namespace TournamentManager.Tests.ModelValidators;
public class TeamVenueValidatorTests
{
private readonly ITenantContext _tenantContext;
#pragma warning disable IDE0052 // Remove unread private members
private readonly AppDb _appDb; // mocked in CTOR
#pragma warning restore IDE0052 // Remove unread private members

public TeamVenueValidatorTests()
{
Expand Down Expand Up @@ -50,8 +47,6 @@ public TeamVenueValidatorTests()

_tenantContext = tenantContextMock.Object;

_appDb = appDbMock.Object;

#endregion
}

Expand Down
Loading

0 comments on commit 5b1b74d

Please sign in to comment.