@ -11,43 +11,50 @@ import SwiftUI
@ Observable
final class TeamRegistration : BaseTeamRegistration , SideStorable {
// s t a t i c f u n c r e s o u r c e N a m e ( ) - > S t r i n g { " t e a m - r e g i s t r a t i o n s " }
// s t a t i c f u n c t o k e n E x e m p t e d M e t h o d s ( ) - > [ H T T P M e t h o d ] { r e t u r n [ ] }
// s t a t i c f u n c f i l t e r B y S t o r e I d e n t i f i e r ( ) - > B o o l { r e t u r n t r u e }
// s t a t i c v a r r e l a t i o n s h i p N a m e s : [ S t r i n g ] = [ ]
//
// v a r i d : S t r i n g = S t o r e . r a n d o m I d ( )
// v a r l a s t U p d a t e : D a t e
// v a r t o u r n a m e n t : S t r i n g
// v a r g r o u p S t a g e : S t r i n g ?
// v a r r e g i s t r a t i o n D a t e : D a t e ?
// v a r c a l l D a t e : D a t e ?
// v a r b r a c k e t P o s i t i o n : I n t ?
// v a r g r o u p S t a g e P o s i t i o n : I n t ?
// v a r c o m m e n t : S t r i n g ?
// v a r s o u r c e : S t r i n g ?
// v a r s o u r c e V a l u e : S t r i n g ?
// v a r l o g o : S t r i n g ?
// v a r n a m e : S t r i n g ?
//
// v a r w a l k O u t : B o o l = f a l s e
// v a r w i l d C a r d B r a c k e t : B o o l = f a l s e
// v a r w i l d C a r d G r o u p S t a g e : B o o l = f a l s e
// v a r w e i g h t : I n t = 0
// v a r l o c k e d W e i g h t : I n t ?
// v a r c o n f i r m a t i o n D a t e : D a t e ?
// v a r q u a l i f i e d : B o o l = f a l s e
// v a r f i n a l R a n k i n g : I n t ?
// v a r p o i n t s E a r n e d : I n t ?
//
// v a r s t o r e I d : S t r i n g ? = n i l
init ( tournament : String , groupStage : String ? = nil , registrationDate : Date ? = nil , callDate : Date ? = nil , bracketPosition : Int ? = nil , groupStagePosition : Int ? = nil , comment : String ? = nil , source : String ? = nil , sourceValue : String ? = nil , logo : String ? = nil , name : String ? = nil , walkOut : Bool = false , wildCardBracket : Bool = false , wildCardGroupStage : Bool = false , weight : Int = 0 , lockedWeight : Int ? = nil , confirmationDate : Date ? = nil , qualified : Bool = false ) {
// s t a t i c f u n c r e s o u r c e N a m e ( ) - > S t r i n g { " t e a m - r e g i s t r a t i o n s " }
// s t a t i c f u n c t o k e n E x e m p t e d M e t h o d s ( ) - > [ H T T P M e t h o d ] { r e t u r n [ ] }
// s t a t i c f u n c f i l t e r B y S t o r e I d e n t i f i e r ( ) - > B o o l { r e t u r n t r u e }
// s t a t i c v a r r e l a t i o n s h i p N a m e s : [ S t r i n g ] = [ ]
//
// v a r i d : S t r i n g = S t o r e . r a n d o m I d ( )
// v a r l a s t U p d a t e : D a t e
// v a r t o u r n a m e n t : S t r i n g
// v a r g r o u p S t a g e : S t r i n g ?
// v a r r e g i s t r a t i o n D a t e : D a t e ?
// v a r c a l l D a t e : D a t e ?
// v a r b r a c k e t P o s i t i o n : I n t ?
// v a r g r o u p S t a g e P o s i t i o n : I n t ?
// v a r c o m m e n t : S t r i n g ?
// v a r s o u r c e : S t r i n g ?
// v a r s o u r c e V a l u e : S t r i n g ?
// v a r l o g o : S t r i n g ?
// v a r n a m e : S t r i n g ?
//
// v a r w a l k O u t : B o o l = f a l s e
// v a r w i l d C a r d B r a c k e t : B o o l = f a l s e
// v a r w i l d C a r d G r o u p S t a g e : B o o l = f a l s e
// v a r w e i g h t : I n t = 0
// v a r l o c k e d W e i g h t : I n t ?
// v a r c o n f i r m a t i o n D a t e : D a t e ?
// v a r q u a l i f i e d : B o o l = f a l s e
// v a r f i n a l R a n k i n g : I n t ?
// v a r p o i n t s E a r n e d : I n t ?
//
// v a r s t o r e I d : S t r i n g ? = n i l
init (
tournament : String , groupStage : String ? = nil , registrationDate : Date ? = nil ,
callDate : Date ? = nil , bracketPosition : Int ? = nil , groupStagePosition : Int ? = nil ,
comment : String ? = nil , source : String ? = nil , sourceValue : String ? = nil ,
logo : String ? = nil , name : String ? = nil , walkOut : Bool = false ,
wildCardBracket : Bool = false , wildCardGroupStage : Bool = false , weight : Int = 0 ,
lockedWeight : Int ? = nil , confirmationDate : Date ? = nil , qualified : Bool = false
) {
super . init ( )
// s e l f . s t o r e I d = t o u r n a m e n t
// s e l f . s t o r e I d = t o u r n a m e n t
self . tournament = tournament
self . groupStage = groupStage
self . registrationDate = registrationDate ? ? Date ( )
@ -67,83 +74,85 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
self . confirmationDate = confirmationDate
self . qualified = qualified
}
func hasRegisteredOnline ( ) -> Bool {
players ( ) . anySatisfy ( { $0 . registeredOnline } )
}
func unrankedOrUnknown ( ) -> Bool {
players ( ) . anySatisfy ( { $0 . source = = nil } )
}
func isOutOfTournament ( ) -> Bool {
walkOut
}
required init ( from decoder : any Decoder ) throws {
try super . init ( from : decoder )
}
var tournamentStore : TournamentStore ? {
return TournamentLibrary . shared . store ( tournamentId : self . tournament )
}
// MARK: - C o m p u t e d d e p e n d e n c i e s
func unsortedPlayers ( ) -> [ PlayerRegistration ] {
guard let tournamentStore = self . tournamentStore else { return [ ] }
return tournamentStore . playerRegistrations . filter { $0 . teamRegistration = = self . id && $0 . coach = = false }
return tournamentStore . playerRegistrations . filter {
$0 . teamRegistration = = self . id && $0 . coach = = false
}
}
// MARK: -
func deleteTeamScores ( ) {
guard let tournamentStore = self . tournamentStore else { return }
let ts = tournamentStore . teamScores . filter ( { $0 . teamRegistration = = id } )
tournamentStore . teamScores . delete ( contentOfs : ts )
}
override func deleteDependencies ( ) {
let unsortedPlayers = unsortedPlayers ( )
for player in unsortedPlayers {
player . deleteDependencies ( )
}
self . tournamentStore ? . playerRegistrations . deleteDependencies ( unsortedPlayers )
let teamScores = teamScores ( )
for teamScore in teamScores {
teamScore . deleteDependencies ( )
}
self . tournamentStore ? . teamScores . deleteDependencies ( teamScores )
}
func hasArrived ( isHere : Bool = false ) {
let unsortedPlayers = unsortedPlayers ( )
unsortedPlayers . forEach ( { $0 . hasArrived = ! isHere } )
self . tournamentStore ? . playerRegistrations . addOrUpdate ( contentOfs : unsortedPlayers )
}
func isHere ( ) -> Bool {
let unsortedPlayers = unsortedPlayers ( )
if unsortedPlayers . isEmpty { return false }
return unsortedPlayers . allSatisfy ( { $0 . hasArrived } )
}
func isSeedable ( ) -> Bool {
bracketPosition = = nil && groupStage = = nil
}
func setSeedPosition ( inSpot match : Match , slot : TeamPosition ? , opposingSeeding : Bool ) {
var teamPosition : TeamPosition {
var teamPosition : TeamPosition {
if let slot {
return slot
} else {
let matchIndex = match . index
let seedRound = RoundRule . roundIndex ( fromMatchIndex : matchIndex )
let numberOfMatches = RoundRule . numberOfMatches ( forRoundIndex : seedRound )
let isUpper = RoundRule . matchIndexWithinRound ( fromMatchIndex : matchIndex ) < ( numberOfMatches / 2 )
let isUpper =
RoundRule . matchIndexWithinRound ( fromMatchIndex : matchIndex )
< ( numberOfMatches / 2 )
var teamPosition = slot ? ? ( isUpper ? . one : . two )
if opposingSeeding {
teamPosition = slot ? ? ( isUpper ? . two : . one )
@ -160,7 +169,9 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
}
if let tournament = tournamentObject ( ) {
if let index = index ( in : tournament . selectedSortedTeams ( ) ) {
let drawLog = DrawLog ( tournament : tournament . id , drawSeed : index , drawMatchIndex : match . index , drawTeamPosition : teamPosition , drawType : . seed )
let drawLog = DrawLog (
tournament : tournament . id , drawSeed : index , drawMatchIndex : match . index ,
drawTeamPosition : teamPosition , drawType : . seed )
do {
try tournamentStore ? . drawLogs . addOrUpdate ( instance : drawLog )
} catch {
@ -170,7 +181,7 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
tournament . updateTeamScores ( in : bracketPosition )
}
}
func expectedSummonDate ( ) -> Date ? {
if let groupStageStartDate = groupStageObject ( ) ? . startDate {
return groupStageStartDate
@ -179,11 +190,11 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
}
return nil
}
var initialWeight : Int {
return lockedWeight ? ? weight
}
func called ( ) -> Bool {
return callDate != nil
}
@ -195,36 +206,36 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
func getPhoneNumbers ( ) -> [ String ] {
return players ( ) . compactMap { $0 . phoneNumber } . filter ( { $0 . isEmpty = = false } )
}
func getMail ( ) -> [ String ] {
let mails = players ( ) . compactMap ( { $0 . email } )
return mails
}
func isImported ( ) -> Bool {
let unsortedPlayers = unsortedPlayers ( )
if unsortedPlayers . isEmpty { return false }
return unsortedPlayers . allSatisfy ( { $0 . isImported ( ) } )
}
func isWildCard ( ) -> Bool {
return wildCardBracket || wildCardGroupStage
}
func isPlaying ( ) -> Bool {
return currentMatch ( ) != nil
}
func currentMatch ( ) -> Match ? {
return teamScores ( ) . compactMap { $0 . matchObject ( ) } . first ( where : { $0 . isRunning ( ) } )
}
func teamScores ( ) -> [ TeamScore ] {
guard let tournamentStore = self . tournamentStore else { return [ ] }
return tournamentStore . teamScores . filter ( { $0 . teamRegistration = = id } )
}
func wins ( ) -> [ Match ] {
guard let tournamentStore = self . tournamentStore else { return [ ] }
return tournamentStore . matches . filter ( { $0 . winningTeamId = = id } )
@ -234,7 +245,7 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
guard let tournamentStore = self . tournamentStore else { return [ ] }
return tournamentStore . matches . filter ( { $0 . losingTeamId = = id } )
}
func matches ( ) -> [ Match ] {
guard let tournamentStore = self . tournamentStore else { return [ ] }
return tournamentStore . matches . filter ( { $0 . losingTeamId = = id || $0 . winningTeamId = = id } )
@ -243,62 +254,74 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
var tournamentCategory : TournamentCategory {
tournamentObject ( ) ? . tournamentCategory ? ? . men
}
@objc
var canonicalName : String {
players ( ) . map { $0 . canonicalName } . joined ( separator : " " )
}
func hasMemberOfClub ( _ codeClubOrClubName : String ? ) -> Bool {
guard let codeClubOrClubName else { return true }
return unsortedPlayers ( ) . anySatisfy ( {
$0 . clubName ? . contains ( codeClubOrClubName ) = = true || $0 . clubName ? . contains ( codeClubOrClubName ) = = true
$0 . clubName ? . contains ( codeClubOrClubName ) = = true
|| $0 . clubName ? . contains ( codeClubOrClubName ) = = true
} )
}
func updateWeight ( inTournamentCategory tournamentCategory : TournamentCategory ) {
self . setWeight ( from : self . players ( ) , inTournamentCategory : tournamentCategory )
}
func teamLabel ( _ displayStyle : DisplayStyle = . wide , twoLines : Bool = false , separator : String = " & " ) -> String {
func teamLabel (
_ displayStyle : DisplayStyle = . wide , twoLines : Bool = false , separator : String = " & "
) -> String {
if let name { return name }
return players ( ) . map { $0 . playerLabel ( displayStyle ) } . joined ( separator : twoLines ? " \n " : " \( separator ) " )
return players ( ) . map { $0 . playerLabel ( displayStyle ) } . joined (
separator : twoLines ? " \n " : " \( separator ) " )
}
func teamLabelRanked ( displayRank : Bool , displayTeamName : Bool ) -> String {
[ displayTeamName ? name : nil , displayRank ? seedIndex ( ) : nil , displayTeamName ? ( name = = nil ? teamLabel ( ) : name ) : teamLabel ( ) ] . compactMap ( { $0 } ) . joined ( separator : " " )
[
displayTeamName ? name : nil , displayRank ? seedIndex ( ) : nil ,
displayTeamName ? ( name = = nil ? teamLabel ( ) : name ) : teamLabel ( ) ,
] . compactMap ( { $0 } ) . joined ( separator : " " )
}
func seedIndex ( ) -> String ? {
guard let tournament = tournamentObject ( ) else { return nil }
guard let index = index ( in : tournament . selectedSortedTeams ( ) ) else { return nil }
return " ( \( index + 1 ) ) "
}
func index ( in teams : [ TeamRegistration ] ) -> Int ? {
return teams . firstIndex ( where : { $0 . id = = id } )
}
func formattedSeed ( in teams : [ TeamRegistration ] ) -> String {
if let index = index ( in : teams ) {
func formattedSeed ( in teams : [ TeamRegistration ] ? = nil ) -> String {
let selectedSortedTeams = teams ? ? tournamentObject ( ) ? . selectedSortedTeams ( ) ? ? [ ]
if let index = index ( in : selectedSortedTeams ) {
return " # \( index + 1 ) "
} else {
return " ### "
}
}
func contains ( _ searchField : String ) -> Bool {
return unsortedPlayers ( ) . anySatisfy ( { $0 . contains ( searchField ) } ) || self . name ? . localizedCaseInsensitiveContains ( searchField ) = = true
return unsortedPlayers ( ) . anySatisfy ( { $0 . contains ( searchField ) } )
|| self . name ? . localizedCaseInsensitiveContains ( searchField ) = = true
}
func containsExactlyPlayerLicenses ( _ playerLicenses : [ String ? ] ) -> Bool {
let arrayOfIds : [ String ] = unsortedPlayers ( ) . compactMap ( { $0 . licenceId ? . strippedLicense ? . canonicalVersion } )
let ids : Set < String > = Set < String > ( arrayOfIds . sorted ( ) )
let searchedIds = Set < String > ( playerLicenses . compactMap ( { $0 ? . strippedLicense ? . canonicalVersion } ) . sorted ( ) )
let arrayOfIds : [ String ] = unsortedPlayers ( ) . compactMap ( {
$0 . licenceId ? . strippedLicense ? . canonicalVersion
} )
let ids : Set < String > = Set < String > ( arrayOfIds . sorted ( ) )
let searchedIds = Set < String > (
playerLicenses . compactMap ( { $0 ? . strippedLicense ? . canonicalVersion } ) . sorted ( ) )
if ids . isEmpty || searchedIds . isEmpty { return false }
return ids . hashValue = = searchedIds . hashValue
}
func includes ( players : [ PlayerRegistration ] ) -> Bool {
let unsortedPlayers = unsortedPlayers ( )
guard players . count = = unsortedPlayers . count else { return false }
@ -308,32 +331,33 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
}
}
}
func includes ( player : PlayerRegistration ) -> Bool {
return unsortedPlayers ( ) . anySatisfy { _player in
_player . isSameAs ( player )
}
}
func canPlay ( ) -> Bool {
let unsortedPlayers = unsortedPlayers ( )
if unsortedPlayers . isEmpty { return false }
return matches ( ) . isEmpty = = false || unsortedPlayers . allSatisfy ( { $0 . hasPaid ( ) || $0 . hasArrived } )
return matches ( ) . isEmpty = = false
|| unsortedPlayers . allSatisfy ( { $0 . hasPaid ( ) || $0 . hasArrived } )
}
func availableForSeedPick ( ) -> Bool {
return groupStage = = nil && bracketPosition = = nil
}
func inGroupStage ( ) -> Bool {
return groupStagePosition != nil
}
func inRound ( ) -> Bool {
return bracketPosition != nil
}
func positionLabel ( ) -> String ? {
if groupStagePosition != nil { return " Poule " }
if let initialRound = initialRound ( ) {
@ -342,62 +366,75 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
return nil
}
}
func initialRoundColor ( ) -> Color ? {
if walkOut { return Color . logoRed }
if groupStagePosition != nil { return Color . blue }
if let initialRound = initialRound ( ) , let colorHex = RoundRule . colors [ safe : initialRound . index ] {
if let initialRound = initialRound ( ) ,
let colorHex = RoundRule . colors [ safe : initialRound . index ]
{
return Color ( uiColor : . init ( fromHex : colorHex ) )
} else {
return nil
}
}
func resetGroupeStagePosition ( ) {
guard let tournamentStore = self . tournamentStore else { return }
if let groupStage {
let matches = tournamentStore . matches . filter ( { $0 . groupStage = = groupStage } ) . map { $0 . id }
let teamScores = tournamentStore . teamScores . filter ( { $0 . teamRegistration = = id && matches . contains ( $0 . match ) } )
let matches = tournamentStore . matches . filter ( { $0 . groupStage = = groupStage } ) . map {
$0 . id
}
let teamScores = tournamentStore . teamScores . filter ( {
$0 . teamRegistration = = id && matches . contains ( $0 . match )
} )
tournamentStore . teamScores . delete ( contentOfs : teamScores )
}
// g r o u p S t a g e O b j e c t ( ) ? . _ m a t c h e s ( ) . f o r E a c h ( { $ 0 . u p d a t e T e a m S c o r e s ( ) } )
groupStage = nil
groupStagePosition = nil
}
func resetBracketPosition ( ) {
guard let tournamentStore = self . tournamentStore else { return }
let matches = tournamentStore . matches . filter ( { $0 . groupStage = = nil } ) . map { $0 . id }
let teamScores = tournamentStore . teamScores . filter ( { $0 . teamRegistration = = id && matches . contains ( $0 . match ) } )
let teamScores = tournamentStore . teamScores . filter ( {
$0 . teamRegistration = = id && matches . contains ( $0 . match )
} )
tournamentStore . teamScores . delete ( contentOfs : teamScores )
self . bracketPosition = nil
}
func resetPositions ( ) {
resetGroupeStagePosition ( )
resetBracketPosition ( )
resetBracketPosition ( )
}
func pasteData ( _ exportFormat : ExportFormat = . rawText , _ index : Int = 0 ) -> String {
switch exportFormat {
case . rawText :
return [ playersPasteData ( exportFormat ) , formattedInscriptionDate ( exportFormat ) , name ] . compactMap ( { $0 } ) . joined ( separator : exportFormat . newLineSeparator ( ) )
return [ playersPasteData ( exportFormat ) , formattedInscriptionDate ( exportFormat ) , name ]
. compactMap ( { $0 } ) . joined ( separator : exportFormat . newLineSeparator ( ) )
case . csv :
return [ index . formatted ( ) , playersPasteData ( exportFormat ) , isWildCard ( ) ? " WC " : weight . formatted ( ) ] . joined ( separator : exportFormat . separator ( ) )
return [
index . formatted ( ) , playersPasteData ( exportFormat ) ,
isWildCard ( ) ? " WC " : weight . formatted ( ) ,
] . joined ( separator : exportFormat . separator ( ) )
}
}
var computedRegistrationDate : Date {
return registrationDate ? ? . distantFuture
}
func formattedInscriptionDate ( _ exportFormat : ExportFormat = . rawText ) -> String ? {
guard let registrationDate else { return nil }
let formattedDate = registrationDate . formatted ( . dateTime . weekday ( ) . day ( ) . month ( ) . hour ( ) . minute ( ) )
let formattedDate = registrationDate . formatted (
. dateTime . weekday ( ) . day ( ) . month ( ) . hour ( ) . minute ( ) )
let onlineSuffix = hasRegisteredOnline ( ) ? " en ligne " : " "
switch exportFormat {
case . rawText :
return " Inscrit \( onlineSuffix ) le \( formattedDate ) "
@ -405,13 +442,14 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
return formattedDate
}
}
func formattedSummonDate ( _ exportFormat : ExportFormat = . rawText ) -> String ? {
switch exportFormat {
case . rawText :
if let callDate {
return " Convoqué le " + callDate . formatted ( . dateTime . weekday ( ) . day ( ) . month ( ) . hour ( ) . minute ( ) )
return " Convoqué le "
+ callDate . formatted ( . dateTime . weekday ( ) . day ( ) . month ( ) . hour ( ) . minute ( ) )
} else {
return nil
}
@ -423,22 +461,31 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
}
}
}
func playersPasteData ( _ exportFormat : ExportFormat = . rawText ) -> String {
switch exportFormat {
case . rawText :
return players ( ) . map { $0 . pasteData ( exportFormat ) } . joined ( separator : exportFormat . newLineSeparator ( ) )
return players ( ) . map { $0 . pasteData ( exportFormat ) } . joined (
separator : exportFormat . newLineSeparator ( ) )
case . csv :
return players ( ) . map { [ $0 . pasteData ( exportFormat ) , isWildCard ( ) ? " WC " : $0 . computedRank . formatted ( ) ] . joined ( separator : exportFormat . separator ( ) ) } . joined ( separator : exportFormat . separator ( ) )
return players ( ) . map {
[ $0 . pasteData ( exportFormat ) , isWildCard ( ) ? " WC " : $0 . computedRank . formatted ( ) ]
. joined ( separator : exportFormat . separator ( ) )
} . joined ( separator : exportFormat . separator ( ) )
}
}
func updatePlayers ( _ players : Set < PlayerRegistration > , inTournamentCategory tournamentCategory : TournamentCategory ) {
func updatePlayers (
_ players : Set < PlayerRegistration > ,
inTournamentCategory tournamentCategory : TournamentCategory
) {
let previousPlayers = Set ( unsortedPlayers ( ) )
players . forEach { player in
previousPlayers . forEach { oldPlayer in
if player . licenceId ? . strippedLicense = = oldPlayer . licenceId ? . strippedLicense , player . licenceId ? . strippedLicense != nil {
if player . licenceId ? . strippedLicense = = oldPlayer . licenceId ? . strippedLicense ,
player . licenceId ? . strippedLicense != nil
{
player . registeredOnline = oldPlayer . registeredOnline
player . coach = oldPlayer . coach
player . tournamentPlayed = oldPlayer . tournamentPlayed
@ -449,8 +496,7 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
}
}
}
let playersToRemove = previousPlayers . subtracting ( players )
self . tournamentStore ? . playerRegistrations . delete ( contentOfs : playersToRemove )
setWeight ( from : Array ( players ) , inTournamentCategory : tournamentCategory )
@ -458,16 +504,16 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
players . forEach { player in
player . teamRegistration = id
}
// d o {
// t r y s e l f . t o u r n a m e n t S t o r e . p l a y e r R e g i s t r a t i o n s . a d d O r U p d a t e ( c o n t e n t O f s : p l a y e r s )
// } c a t c h {
// L o g g e r . e r r o r ( e r r o r )
// }
}
// d o {
// t r y s e l f . t o u r n a m e n t S t o r e . p l a y e r R e g i s t r a t i o n s . a d d O r U p d a t e ( c o n t e n t O f s : p l a y e r s )
// } c a t c h {
// L o g g e r . e r r o r ( e r r o r )
// }
}
typealias TeamRange = ( left : TeamRegistration ? , right : TeamRegistration ? )
func replacementRange ( ) -> TeamRange ? {
guard let tournamentObject = tournamentObject ( ) else { return nil }
guard let index = tournamentObject . indexOf ( team : self ) else { return nil }
@ -476,7 +522,7 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
let right = selectedSortedTeams [ safe : index + 1 ]
return ( left : left , right : right )
}
func replacementRangeExtended ( ) -> TeamRange ? {
guard let tournamentObject = tournamentObject ( ) else { return nil }
guard let groupStagePosition else { return nil }
@ -485,19 +531,23 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
if groupStagePosition = = 0 {
left = tournamentObject . seeds ( ) . last
} else {
let previousHat = selectedSortedTeams . filter ( { $0 . groupStagePosition = = groupStagePosition - 1 } ) . sorted ( by : \ . weight )
let previousHat = selectedSortedTeams . filter ( {
$0 . groupStagePosition = = groupStagePosition - 1
} ) . sorted ( by : \ . weight )
left = previousHat . last
}
var right : TeamRegistration ? = nil
if groupStagePosition = = tournamentObject . teamsPerGroupStage - 1 {
right = nil
} else {
let previousHat = selectedSortedTeams . filter ( { $0 . groupStagePosition = = groupStagePosition + 1 } ) . sorted ( by : \ . weight )
let previousHat = selectedSortedTeams . filter ( {
$0 . groupStagePosition = = groupStagePosition + 1
} ) . sorted ( by : \ . weight )
right = previousHat . first
}
return ( left : left , right : right )
}
typealias AreInIncreasingOrder = ( PlayerRegistration , PlayerRegistration ) -> Bool
func players ( ) -> [ PlayerRegistration ] {
@ -506,36 +556,43 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
let predicates : [ AreInIncreasingOrder ] = [
{ $0 . sex ? . rawValue ? ? 0 < $1 . sex ? . rawValue ? ? 0 } ,
{ $0 . rank ? ? Int . max < $1 . rank ? ? Int . max } ,
{ $0 . lastName < $1 . lastName } ,
{ $0 . firstName < $1 . firstName }
{ $0 . lastName < $1 . lastName } ,
{ $0 . firstName < $1 . firstName } ,
]
for predicate in predicates {
if ! predicate ( lhs , rhs ) && ! predicate ( rhs , lhs ) {
continue
}
return predicate ( lhs , rhs )
}
return false
}
}
func coaches ( ) -> [ PlayerRegistration ] {
guard let store = self . tournamentStore else { return [ ] }
return store . playerRegistrations . filter { $0 . coach }
}
func setWeight ( from players : [ PlayerRegistration ] , inTournamentCategory tournamentCategory : TournamentCategory ) {
func setWeight (
from players : [ PlayerRegistration ] ,
inTournamentCategory tournamentCategory : TournamentCategory
) {
let significantPlayerCount = significantPlayerCount ( )
weight = ( players . prefix ( significantPlayerCount ) . map { $0 . computedRank } + missingPlayerType ( inTournamentCategory : tournamentCategory ) . map { unrankValue ( for : $0 = = 1 ? true : false ) } ) . prefix ( significantPlayerCount ) . reduce ( 0 , + )
weight =
( players . prefix ( significantPlayerCount ) . map { $0 . computedRank }
+ missingPlayerType ( inTournamentCategory : tournamentCategory ) . map {
unrankValue ( for : $0 = = 1 ? true : false )
} ) . prefix ( significantPlayerCount ) . reduce ( 0 , + )
}
func significantPlayerCount ( ) -> Int {
return tournamentObject ( ) ? . significantPlayerCount ( ) ? ? 2
}
func missingPlayerType ( inTournamentCategory tournamentCategory : TournamentCategory ) -> [ Int ] {
let players = unsortedPlayers ( )
if players . count >= 2 { return [ ] }
@ -548,16 +605,16 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
}
return missing
}
func unrankValue ( for malePlayer : Bool ) -> Int {
return tournamentObject ( ) ? . unrankValue ( for : malePlayer ) ? ? 90_000
}
func groupStageObject ( ) -> GroupStage ? {
guard let groupStage else { return nil }
return self . tournamentStore ? . groupStages . findById ( groupStage )
}
func initialRound ( ) -> Round ? {
guard let bracketPosition else { return nil }
let roundIndex = RoundRule . roundIndex ( fromMatchIndex : bracketPosition / 2 )
@ -567,22 +624,23 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
func initialMatch ( ) -> Match ? {
guard let bracketPosition else { return nil }
guard let initialRoundObject = initialRound ( ) else { return nil }
return self . tournamentStore ? . matches . first ( where : { $0 . round = = initialRoundObject . id && $0 . index = = bracketPosition / 2 } )
return self . tournamentStore ? . matches . first ( where : {
$0 . round = = initialRoundObject . id && $0 . index = = bracketPosition / 2
} )
}
func toggleSummonConfirmation ( ) {
if confirmationDate = = nil { confirmationDate = Date ( ) }
else { confirmationDate = nil }
if confirmationDate = = nil { confirmationDate = Date ( ) } else { confirmationDate = nil }
}
func didConfirmSummon ( ) -> Bool {
confirmationDate != nil
}
func tournamentObject ( ) -> Tournament ? {
return Store . main . findById ( tournament )
}
func groupStagePositionAtStep ( _ step : Int ) -> Int ? {
guard let groupStagePosition else { return nil }
if step = = 0 {
@ -592,33 +650,36 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
}
return nil
}
func wildcardLabel ( ) -> String ? {
if isWildCard ( ) {
let wildcardLabel : String = [ " wildcard " , ( wildCardBracket ? " tableau " : " poule " ) ] . joined ( separator : " " )
let wildcardLabel : String = [ " wildcard " , ( wildCardBracket ? " tableau " : " poule " ) ]
. joined ( separator : " " )
return wildcardLabel
} else {
return nil
}
}
var _cachedRestingTime : ( Bool , Date ? ) ?
func restingTime ( ) -> Date ? {
if let _cachedRestingTime { return _cachedRestingTime . 1 }
let restingTime = matches ( ) . filter ( { $0 . hasEnded ( ) } ) . sorted ( by : \ . computedEndDateForSorting ) . last ? . endDate
let restingTime = matches ( ) . filter ( { $0 . hasEnded ( ) } ) . sorted (
by : \ . computedEndDateForSorting
) . last ? . endDate
_cachedRestingTime = ( true , restingTime )
return restingTime
}
func resetRestingTime ( ) {
_cachedRestingTime = nil
}
var restingTimeForSorting : Date {
restingTime ( ) !
}
func teamNameLabel ( ) -> String {
if let name , name . isEmpty = = false {
return name
@ -626,25 +687,29 @@ final class TeamRegistration: BaseTeamRegistration, SideStorable {
return " Toute l'équipe "
}
}
func isDifferentPosition ( _ drawMatchIndex : Int ? ) -> Bool {
if let bracketPosition , let drawMatchIndex {
return drawMatchIndex != bracketPosition
} else if let bracketPosition {
} else if bracketPosition != nil {
return true
} else if let drawMatchIndex {
} else if drawMatchIndex != nil {
return true
}
return false
}
func shouldDisplayRankAndWeight ( ) -> Bool {
unsortedPlayers ( ) . count > 0
}
func insertOnServer ( ) {
self . tournamentStore ? . teamRegistrations . writeChangeAndInsertOnServer ( instance : self )
for playerRegistration in self . unsortedPlayers ( ) {
playerRegistration . insertOnServer ( )
}
}
}
enum TeamDataSource : Int , Codable {