@ -32,6 +32,7 @@ final class MatchScheduler : ModelObject, Storable {
var overrideCourtsUnavailability : Bool = false
var shouldTryToFillUpCourtsAvailable : Bool = true
var courtsAvailable : Set < Int > = Set < Int > ( )
var simultaneousStart : Bool = true
init ( tournament : String ,
timeDifferenceLimit : Int = 5 ,
@ -46,7 +47,8 @@ final class MatchScheduler : ModelObject, Storable {
groupStageChunkCount : Int ? = nil ,
overrideCourtsUnavailability : Bool = false ,
shouldTryToFillUpCourtsAvailable : Bool = true ,
courtsAvailable : Set < Int > = Set < Int > ( ) ) {
courtsAvailable : Set < Int > = Set < Int > ( ) ,
simultaneousStart : Bool = true ) {
self . tournament = tournament
self . timeDifferenceLimit = timeDifferenceLimit
self . loserBracketRotationDifference = loserBracketRotationDifference
@ -61,6 +63,7 @@ final class MatchScheduler : ModelObject, Storable {
self . overrideCourtsUnavailability = overrideCourtsUnavailability
self . shouldTryToFillUpCourtsAvailable = shouldTryToFillUpCourtsAvailable
self . courtsAvailable = courtsAvailable
self . simultaneousStart = simultaneousStart
}
enum CodingKeys : String , CodingKey {
@ -79,6 +82,7 @@ final class MatchScheduler : ModelObject, Storable {
case _overrideCourtsUnavailability = " overrideCourtsUnavailability "
case _shouldTryToFillUpCourtsAvailable = " shouldTryToFillUpCourtsAvailable "
case _courtsAvailable = " courtsAvailable "
case _simultaneousStart = " simultaneousStart "
}
var courtsUnavailability : [ DateInterval ] ? {
@ -185,15 +189,19 @@ final class MatchScheduler : ModelObject, Storable {
// G e t t h e m a x i m u m c o u n t o f m a t c h e s i n a n y g r o u p
let maxMatchesCount = _groupStages . map { $0 . _matches ( ) . count } . max ( ) ? ? 0
var flattenedMatches = [ Match ] ( )
if simultaneousStart {
// F l a t t e n m a t c h e s i n a r o u n d - r o b i n o r d e r b y c y c l i n g t h r o u g h e a c h g r o u p
let flattenedMatches = ( 0. . < maxMatchesCount ) . flatMap { index in
flattenedMatches = ( 0. . < maxMatchesCount ) . flatMap { index in
_groupStages . compactMap { group in
// S a f e l y a c c e s s m a t c h e s , r e t u r n n i l i f i n d e x i s o u t o f b o u n d s
let playedMatches = group . playedMatches ( )
return playedMatches . indices . contains ( index ) ? playedMatches [ index ] : nil
}
}
} else {
flattenedMatches = _groupStages . flatMap ( { $0 . playedMatches ( ) } )
}
var slots = [ GroupStageTimeMatch ] ( )
var availableMatches = flattenedMatches
@ -214,17 +222,21 @@ final class MatchScheduler : ModelObject, Storable {
let counts = Dictionary ( previousRotationBracketIndexes , uniquingKeysWith : + )
var rotationMatches = Array ( availableMatches . filter ( { match in
// C h e c k i f a l l t e a m s f r o m t h e m a t c h a r e n o t a l r e a d y s c h e d u l e d i n t h e c u r r e n t r o t a t i o n
let teamsAvailable = teamsPerRotation [ rotationIndex ] ! . allSatisfy ( { ! match . containsTeamId ( $0 ) } )
let teamsAvailable = teamsPerRotation [ rotationIndex ] ! . allSatisfy ( { ! match . containsTeamIn dex ( $0 ) } )
if ! teamsAvailable {
print ( " Match \( match . roundAndMatchTitle ( ) ) has teams already scheduled in rotation \( rotationIndex ) " )
}
return teamsAvailable
} ) . prefix ( courtsAvailable . count ) )
} ) )
if rotationIndex > 0 {
rotationMatches = rotationMatches . sorted ( by : {
if counts [ $0 . groupStageObject ! . index ] ? ? 0 = = counts [ $1 . groupStageObject ! . index ] ? ? 0 {
if simultaneousStart {
return $0 . groupStageObject ! . orderedIndexOfMatch ( $0 ) < $1 . groupStageObject ! . orderedIndexOfMatch ( $1 )
} else {
return $0 . groupStageObject ! . index < $1 . groupStageObject ! . index
}
} else {
return counts [ $0 . groupStageObject ! . index ] ? ? 0 < counts [ $1 . groupStageObject ! . index ] ? ? 0
}
@ -245,7 +257,7 @@ final class MatchScheduler : ModelObject, Storable {
return false
}
let teamsAvailable = teamsPerRotation [ rotationIndex ] ! . allSatisfy ( { ! match . containsTeamId ( $0 ) } )
let teamsAvailable = teamsPerRotation [ rotationIndex ] ! . allSatisfy ( { ! match . containsTeamIn dex ( $0 ) } )
if ! teamsAvailable {
print ( " Teams from match \( match . roundAndMatchTitle ( ) ) are already scheduled in this rotation " )
return false
@ -259,7 +271,7 @@ final class MatchScheduler : ModelObject, Storable {
print ( " Scheduled match: \( first . roundAndMatchTitle ( ) ) on court \( courtIndex ) at rotation \( rotationIndex ) " )
slots . append ( timeMatch )
teamsPerRotation [ rotationIndex ] ! . append ( contentsOf : first . teamIds ( ) )
teamsPerRotation [ rotationIndex ] ! . append ( contentsOf : first . matchUp ( ) )
rotationMatches . removeAll ( where : { $0 . id = = first . id } )
availableMatches . removeAll ( where : { $0 . id = = first . id } )
@ -891,4 +903,16 @@ extension Match {
func containsTeamId ( _ id : String ) -> Bool {
return teamIds ( ) . contains ( id )
}
func containsTeamIndex ( _ id : String ) -> Bool {
matchUp ( ) . contains ( id )
}
func matchUp ( ) -> [ String ] {
guard let groupStageObject else {
return [ ]
}
return groupStageObject . _matchUp ( for : index ) . map { groupStageObject . id + " _ \( $0 ) " }
}
}