@ -27,6 +27,7 @@ class MatchScheduler : ModelObject, Storable {
var shouldHandleUpperRoundSlice : Bool
var shouldEndRoundBeforeStartingNext : Bool
var groupStageChunkCount : Int ?
var overrideCourtsUnavailability : Bool = false
init ( tournament : String ,
timeDifferenceLimit : Int = 5 ,
@ -38,7 +39,7 @@ class MatchScheduler : ModelObject, Storable {
rotationDifferenceIsImportant : Bool = false ,
shouldHandleUpperRoundSlice : Bool = true ,
shouldEndRoundBeforeStartingNext : Bool = true ,
groupStageChunkCount : Int ? = nil ) {
groupStageChunkCount : Int ? = nil , overrideCourtsUnavailability : Bool = false ) {
self . tournament = tournament
self . timeDifferenceLimit = timeDifferenceLimit
self . loserBracketRotationDifference = loserBracketRotationDifference
@ -50,6 +51,7 @@ class MatchScheduler : ModelObject, Storable {
self . shouldHandleUpperRoundSlice = shouldHandleUpperRoundSlice
self . shouldEndRoundBeforeStartingNext = shouldEndRoundBeforeStartingNext
self . groupStageChunkCount = groupStageChunkCount
self . overrideCourtsUnavailability = overrideCourtsUnavailability
}
enum CodingKeys : String , CodingKey {
@ -65,11 +67,12 @@ class MatchScheduler : ModelObject, Storable {
case _shouldHandleUpperRoundSlice = " shouldHandleUpperRoundSlice "
case _shouldEndRoundBeforeStartingNext = " shouldEndRoundBeforeStartingNext "
case _groupStageChunkCount = " groupStageChunkCount "
case _overrideCourtsUnavailability = " overrideCourtsUnavailability "
}
var courtsUnavailability : [ DateInterval ] ? {
guard let event = tournamentObject ( ) ? . eventObject ( ) else { return nil }
return event . courtsUnavailability + event . tournamentsCourtsUsed ( exluding : tournament )
return event . courtsUnavailability + ( overrideCourtsUnavailability ? [ ] : event . tournamentsCourtsUsed ( exluding : tournament ) )
}
var additionalEstimationDuration : Int {
@ -403,7 +406,7 @@ class MatchScheduler : ModelObject, Storable {
if rotationIndex > 0 , let freeCourtPreviousRotation = freeCourtPerRotation [ rotationIndex - 1 ] , freeCourtPreviousRotation . count > 0 {
print ( " scenario where we are waiting for a breaktime to be over without any match to play in between or a free court was available and we need to recheck breaktime left on it " )
let previousPreviousRotationSlots = slots . filter ( { $0 . rotationIndex = = rotationIndex - 2 && freeCourtPreviousRotation . contains ( $0 . courtIndex ) } )
let previousEndDate = getNextStartDate ( fromPreviousRotationSlots : previousPreviousRotationSlots , includeBreakTime : tru e)
let previousEndDate = getNextStartDate ( fromPreviousRotationSlots : previousPreviousRotationSlots , includeBreakTime : accountUpperBracketBreakTim e)
let previousEndDateNoBreak = getNextStartDate ( fromPreviousRotationSlots : previousPreviousRotationSlots , includeBreakTime : false )
let noBreakAlreadyTested = previousRotationSlots . anySatisfy ( { $0 . startDate = = previousEndDateNoBreak } )
@ -420,7 +423,7 @@ class MatchScheduler : ModelObject, Storable {
difference = noBreakAlreadyTested ? differenceWithBreak : max ( differenceWithBreak , differenceWithoutBreak )
}
if difference > timeDifferenceLimitInSeconds {
if difference > timeDifferenceLimitInSeconds && rotationStartDate . addingTimeInterval ( - difference ) != previousEndDate {
courts . removeAll ( where : { index in freeCourtPreviousRotation . contains ( index )
} )
freeCourtPerRotation [ rotationIndex ] = courts
@ -451,12 +454,12 @@ class MatchScheduler : ModelObject, Storable {
}
func dispatchCourts ( availableCourts : Int , courts : [ Int ] , availableMatchs : inout [ Match ] , slots : inout [ TimeMatch ] , rotationIndex : Int , rotationStartDate : Date , freeCourtPerRotation : inout [ Int : [ Int ] ] , courtsUnavailability : [ DateInterval ] ? ) {
var matchPerRound = [ Int : Int ] ( )
var matchPerRound = [ String : Int ] ( )
var minimumTargetedEndDate : Date = rotationStartDate
print ( " dispatchCourts " , courts . sorted ( ) , rotationStartDate , rotationIndex )
courts . sorted ( ) . forEach { courtIndex in
print ( " trying to find a match for \( courtIndex ) in \( rotationIndex ) " )
for ( courtPosition , courtIndex ) in courts . sorted ( ) . enumerated ( ) {
if let first = availableMatchs . first ( where : { match in
print ( " trying to find a match for \( courtIndex ) in \( rotationIndex ) " )
let roundObject = match . roundObject !
let courtsUnavailable = courtsUnavailable ( startDate : rotationStartDate , duration : match . matchFormat . getEstimatedDuration ( additionalEstimationDuration ) , courtsUnavailability : courtsUnavailability )
print ( " courtsUnavailable \( courtsUnavailable ) " )
@ -466,10 +469,11 @@ class MatchScheduler : ModelObject, Storable {
let canBePlayed = roundMatchCanBePlayed ( match , roundObject : roundObject , slots : slots , rotationIndex : rotationIndex , targetedStartDate : rotationStartDate , minimumTargetedEndDate : & minimumTargetedEndDate )
let currentRotationSameRoundMatches = matchPerRound [ roundObject . in dex ] ? ? 0
let currentRotationSameRoundMatches = matchPerRound [ roundObject . id ] ? ? 0
let roundMatchesCount = roundObject . playedMatches ( ) . count
if shouldHandleUpperRoundSlice {
let roundMatchesCount = roundObject . playedMatches ( ) . count
print ( " shouldHandleUpperRoundSlice \( roundMatchesCount ) " )
if roundObject . parent = = nil && roundMatchesCount > courts . count {
print ( " roundMatchesCount \( roundMatchesCount ) > \( courts . count ) " )
@ -480,24 +484,27 @@ class MatchScheduler : ModelObject, Storable {
}
}
// i f a l l i s o k , w e d o a f i n a l c h e c k t o s e e i f t h e f i r s t
let indexInRound = match . indexInRound ( )
print ( " Upper Round, index > 0, first Match of round \( indexInRound ) and more than one court available; looking for next match (same round) \( indexInRound + 1 ) " )
if roundObject . parent = = nil && roundObject . index > 0 , indexInRound = = 0 , courts . count > 1 , let nextMatch = match . next ( ) {
if roundObject . parent = = nil && roundObject . index > 0 , indexInRound = = 0 , let nextMatch = match . next ( ) {
guard courtPosition < courts . count - 1 , courts . count > 1 else {
print ( " next match and this match can not be played at the same time, returning false " )
return false
}
if canBePlayed && roundMatchCanBePlayed ( nextMatch , roundObject : roundObject , slots : slots , rotationIndex : rotationIndex , targetedStartDate : rotationStartDate , minimumTargetedEndDate : & minimumTargetedEndDate ) {
print ( " next match and this match can be played, returning true " )
return true
} else {
print ( " next match and this match can not be played at the same time, returning false " )
return false
}
}
// n o t a d d i n g a l a s t m a t c h o f a 4 - m a t c h r o u n d ( f i n a l n o t i n c l u d e d o b v i o u s l y )
print ( " \( currentRotationSameRoundMatches ) modulo \( currentRotationSameRoundMatches % 2 ) same round match is even, index of round is not 0 and upper bracket. If it's not the last court available \( courtIndex ) == \( courts . count - 1 ) " )
if currentRotationSameRoundMatches % 2 = = 0 && roundObject . index != 0 && roundObject . parent = = nil && courtIndex = = courts . count - 1 {
if roundMatchesCount <= 4 && currentRotationSameRoundMatches % 2 = = 0 && roundObject . index != 0 && roundObject . parent = = nil && ( ( courts . count > 1 && courtPosition > = courts . count - 1 ) || courts . count = = 1 && availableCourts > 1 ) {
print ( " we return false " )
return false
}
@ -508,10 +515,10 @@ class MatchScheduler : ModelObject, Storable {
print ( first . roundObject ! . roundTitle ( ) , first . matchTitle ( ) , courtIndex , rotationStartDate )
if first . roundObject ! . parent = = nil {
if let roundIndex = matchPerRound [ first . roundObject ! . in dex ] {
matchPerRound [ first . roundObject ! . in dex ] = roundIndex + 1
if let roundIndex = matchPerRound [ first . roundObject ! . id ] {
matchPerRound [ first . roundObject ! . id ] = roundIndex + 1
} else {
matchPerRound [ first . roundObject ! . in dex ] = 1
matchPerRound [ first . roundObject ! . id ] = 1
}
}
let timeMatch = TimeMatch ( matchID : first . id , rotationIndex : rotationIndex , courtIndex : courtIndex , startDate : rotationStartDate , durationLeft : first . matchFormat . getEstimatedDuration ( additionalEstimationDuration ) , minimumBreakTime : first . matchFormat . breakTime . breakTime )