@ -267,13 +267,13 @@ struct TableStructureView: View {
}
}
}
}
if groupStageCount > 0 {
// i f g r o u p S t a g e C o u n t > 0 {
LabeledContent {
// L a b e l e d C o n t e n t {
Text ( tf . formatted ( ) )
// T e x t ( t f . f o r m a t t e d ( ) )
} label : {
// } l a b e l : {
Text ( " Effectif " )
// T e x t ( " E f f e c t i f t a b l e a u " )
}
// }
}
// }
} else {
} else {
LabeledContent {
LabeledContent {
let mp1 = teamsPerGroupStage * ( teamsPerGroupStage - 1 ) / 2 * groupStageCount
let mp1 = teamsPerGroupStage * ( teamsPerGroupStage - 1 ) / 2 * groupStageCount
@ -283,16 +283,30 @@ struct TableStructureView: View {
Text ( " Total de matchs " )
Text ( " Total de matchs " )
}
}
}
}
} footer : {
if tsPure > 0 && structurePreset != . doubleGroupStage , groupStageCount > 0 {
LabeledContent {
if tsPure > teamCount / 2 {
FooterButtonView ( " configurer " ) {
Text ( " Le nombre de têtes de série ne devrait pas être supérieur à la moitié de l'effectif. " ) . foregroundStyle ( . red )
showSeedRepartition = true
} else if tsPure < teamCount / 8 {
}
Text ( " À partir du moment où vous avez des têtes de série, leur nombre ne devrait pas être inférieur à 1/8ème de l'effectif. " ) . foregroundStyle ( . red )
} label : {
} else if tsPure < qualifiedFromGroupStage + groupStageAdditionalQualified {
if tournament . state ( ) = = . build {
Text ( " Le nombre de têtes de série ne devrait pas être inférieur au nombre de paires qualifiées sortantes. " ) . foregroundStyle ( . red )
Text ( " Répartition des équipes " )
} else if selectedTournament != nil {
Text ( " La configuration du tournoi séléctionné sera utilisée. " )
} else {
Text ( _seeds ( ) )
}
}
}
}
. onAppear {
if seedRepartition . isEmpty && tournament . state ( ) = = . initial && selectedTournament = = nil {
seedRepartition = HeadManagerView . place ( heads : tsPure , teamsInBracket : tf , initialSeedRound : nil )
}
}
} footer : {
if tsPure > 0 && structurePreset != . doubleGroupStage , groupStageCount > 0 , tsPure < qualifiedFromGroupStage + groupStageAdditionalQualified {
Text ( " Le nombre de têtes de série ne devrait pas être inférieur au nombre de paires qualifiées sortantes. " ) . foregroundStyle ( . red )
}
}
}
if structurePreset . hasWildcards ( ) && tournament . level . wildcardArePossible ( ) {
if structurePreset . hasWildcards ( ) && tournament . level . wildcardArePossible ( ) {
@ -303,27 +317,6 @@ struct TableStructureView: View {
}
}
}
}
if tournament . state ( ) != . build {
Section {
LabeledContent {
Image ( systemName : seedRepartition . isEmpty ? " xmark " : " checkmark " )
} label : {
FooterButtonView ( " Configuration du tableau " ) {
showSeedRepartition = true
}
. disabled ( selectedTournament != nil )
}
} footer : {
if seedRepartition . isEmpty {
Text ( " Aucune répartition n'a été indiqué, vous devrez réserver ou placer les têtes de séries dans le tableau manuellement. " )
} else {
FooterButtonView ( " Supprimer la configuration " , role : . destructive ) {
seedRepartition = [ ]
}
}
}
}
if tournament . rounds ( ) . isEmpty && tournament . state ( ) = = . build {
if tournament . rounds ( ) . isEmpty && tournament . state ( ) = = . build {
Section {
Section {
RowButtonView ( " Ajouter un tableau " , role : . destructive ) {
RowButtonView ( " Ajouter un tableau " , role : . destructive ) {
@ -336,6 +329,12 @@ struct TableStructureView: View {
if tournament . state ( ) != . initial {
if tournament . state ( ) != . initial {
if seedRepartition . isEmpty = = false {
RowButtonView ( " Modifier la répartition des équipes en tableau " , role : . destructive , confirmationMessage : " Cette action va effacer le répartition actuelle des équipes dans le tableau. " ) {
await _handleSeedRepartition ( )
}
}
Section {
Section {
RowButtonView ( " Sauver sans reconstuire l'existant " ) {
RowButtonView ( " Sauver sans reconstuire l'existant " ) {
_saveWithoutRebuild ( )
_saveWithoutRebuild ( )
@ -370,13 +369,6 @@ struct TableStructureView: View {
}
}
}
}
. toolbarBackground ( . visible , for : . navigationBar )
. toolbarBackground ( . visible , for : . navigationBar )
. onChange ( of : teamCount ) {
if teamCount != tournament . teamCount {
updatedElements . insert ( . teamCount )
} else {
updatedElements . remove ( . teamCount )
}
}
. sheet ( isPresented : $ showSeedRepartition , content : {
. sheet ( isPresented : $ showSeedRepartition , content : {
NavigationStack {
NavigationStack {
HeadManagerView ( teamsInBracket : tf , heads : tsPure , initialSeedRepartition : seedRepartition ) { seedRepartition in
HeadManagerView ( teamsInBracket : tf , heads : tsPure , initialSeedRepartition : seedRepartition ) { seedRepartition in
@ -384,6 +376,14 @@ struct TableStructureView: View {
}
}
}
}
} )
} )
. onChange ( of : teamCount ) {
if teamCount != tournament . teamCount {
updatedElements . insert ( . teamCount )
} else {
updatedElements . remove ( . teamCount )
}
_verifyValueIntegrity ( )
}
. onChange ( of : groupStageCount ) {
. onChange ( of : groupStageCount ) {
if groupStageCount != tournament . groupStageCount {
if groupStageCount != tournament . groupStageCount {
updatedElements . insert ( . groupStageCount )
updatedElements . insert ( . groupStageCount )
@ -394,25 +394,31 @@ struct TableStructureView: View {
if structurePreset . isFederalPreset ( ) , groupStageCount = = 0 {
if structurePreset . isFederalPreset ( ) , groupStageCount = = 0 {
teamCount = structurePreset . tableDimension ( )
teamCount = structurePreset . tableDimension ( )
}
}
_verifyValueIntegrity ( )
}
}
. onChange ( of : teamsPerGroupStage ) {
. onChange ( of : teamsPerGroupStage ) {
if teamsPerGroupStage != tournament . teamsPerGroupStage {
if teamsPerGroupStage != tournament . teamsPerGroupStage {
updatedElements . insert ( . teamsPerGroupStage )
updatedElements . insert ( . teamsPerGroupStage )
} else {
} else {
updatedElements . remove ( . teamsPerGroupStage )
updatedElements . remove ( . teamsPerGroupStage )
} }
}
_verifyValueIntegrity ( )
}
. onChange ( of : qualifiedPerGroupStage ) {
. onChange ( of : qualifiedPerGroupStage ) {
if qualifiedPerGroupStage != tournament . qualifiedPerGroupStage {
if qualifiedPerGroupStage != tournament . qualifiedPerGroupStage {
updatedElements . insert ( . qualifiedPerGroupStage )
updatedElements . insert ( . qualifiedPerGroupStage )
} else {
} else {
updatedElements . remove ( . qualifiedPerGroupStage )
updatedElements . remove ( . qualifiedPerGroupStage )
} }
}
_verifyValueIntegrity ( )
}
. onChange ( of : groupStageAdditionalQualified ) {
. onChange ( of : groupStageAdditionalQualified ) {
if groupStageAdditionalQualified != tournament . groupStageAdditionalQualified {
if groupStageAdditionalQualified != tournament . groupStageAdditionalQualified {
updatedElements . insert ( . groupStageAdditionalQualified )
updatedElements . insert ( . groupStageAdditionalQualified )
} else {
} else {
updatedElements . remove ( . groupStageAdditionalQualified )
updatedElements . remove ( . groupStageAdditionalQualified )
}
}
_verifyValueIntegrity ( )
}
}
. toolbar {
. toolbar {
if tournament . state ( ) != . initial {
if tournament . state ( ) != . initial {
@ -484,6 +490,19 @@ struct TableStructureView: View {
}
}
}
}
private func _seeds ( ) -> String {
if seedRepartition . isEmpty || seedRepartition . reduce ( 0 , + ) = = 0 {
return " Aucune configuration "
}
return seedRepartition . enumerated ( ) . compactMap { ( index , count ) in
if count > 0 {
return RoundRule . roundName ( fromRoundIndex : index ) + " : \( count ) "
} else {
return nil
}
} . joined ( separator : " , " )
}
private func _reset ( ) {
private func _reset ( ) {
tournament . removeWildCards ( )
tournament . removeWildCards ( )
@ -573,12 +592,6 @@ struct TableStructureView: View {
}
}
tournament . deleteAndBuildEverything ( preset : structurePreset )
tournament . deleteAndBuildEverything ( preset : structurePreset )
if seedRepartition . count > 0 {
while tournament . rounds ( ) . count < seedRepartition . count {
await tournament . addNewRound ( tournament . rounds ( ) . count )
}
}
if let selectedTournament {
if let selectedTournament {
let oldTournamentStart = selectedTournament . startDate
let oldTournamentStart = selectedTournament . startDate
let newTournamentStart = tournament . startDate
let newTournamentStart = tournament . startDate
@ -614,66 +627,10 @@ struct TableStructureView: View {
}
}
tournament . tournamentStore ? . matches . addOrUpdate ( contentOfs : tournament . _allMatchesIncludingDisabled ( ) )
tournament . tournamentStore ? . matches . addOrUpdate ( contentOfs : tournament . _allMatchesIncludingDisabled ( ) )
} else {
}
for ( index , seedCount ) in seedRepartition . enumerated ( ) {
if let round = tournament . rounds ( ) . first ( where : { $0 . index = = index } ) {
if seedRepartition . count > 0 {
let baseIndex = RoundRule . baseIndex ( forRoundIndex : round . index )
await _handleSeedRepartition ( )
let numberOfMatches = RoundRule . numberOfMatches ( forRoundIndex : round . index )
let playedMatches = round . playedMatches ( ) . map { $0 . index - baseIndex }
let allMatches = round . _matches ( )
let seedSorted = frenchUmpireOrder ( for : numberOfMatches ) . filter ( { index in
playedMatches . contains ( index )
} ) . prefix ( seedCount )
for ( index , value ) in seedSorted . enumerated ( ) {
let isOpponentTurn = index >= playedMatches . count
if let match = allMatches [ safe : value ] {
if match . index - baseIndex < numberOfMatches / 2 {
if isOpponentTurn {
match . previousMatch ( . two ) ? . disableMatch ( )
} else {
match . previousMatch ( . one ) ? . disableMatch ( )
}
} else {
if isOpponentTurn {
match . previousMatch ( . one ) ? . disableMatch ( )
} else {
match . previousMatch ( . two ) ? . disableMatch ( )
}
}
}
}
if seedCount > 0 {
tournament . tournamentStore ? . matches . addOrUpdate ( contentOfs : round . _matches ( ) )
tournament . tournamentStore ? . matches . addOrUpdate ( contentOfs : round . allLoserRoundMatches ( ) )
round . deleteLoserBracket ( )
round . buildLoserBracket ( )
round . loserRounds ( ) . forEach { loserRound in
loserRound . disableUnplayedLoserBracketMatches ( )
}
}
}
}
// i f i n i t i a l S e e d R o u n d > 0 {
// i f l e t r o u n d = t o u r n a m e n t . r o u n d s ( ) . f i r s t ( w h e r e : { $ 0 . i n d e x = = i n i t i a l S e e d R o u n d } ) {
// l e t s e e d S o r t e d = f r e n c h U m p i r e O r d e r ( f o r : R o u n d R u l e . n u m b e r O f M a t c h e s ( f o r R o u n d I n d e x : r o u n d . i n d e x ) )
// p r i n t ( s e e d S o r t e d )
// s e e d S o r t e d . p r e f i x ( i n i t i a l S e e d C o u n t ) . f o r E a c h { i n d e x i n
// i f l e t m a t c h = r o u n d . _ m a t c h e s ( ) [ s a f e : i n d e x ] {
// i f m a t c h . i n d e x I n R o u n d ( ) < R o u n d R u l e . n u m b e r O f M a t c h e s ( f o r R o u n d I n d e x : r o u n d . i n d e x ) / 2 {
// m a t c h . p r e v i o u s M a t c h ( . o n e ) ? . d i s a b l e M a t c h ( )
// } e l s e {
// m a t c h . p r e v i o u s M a t c h ( . t w o ) ? . d i s a b l e M a t c h ( )
// }
// }
// }
//
// i f i n i t i a l S e e d C o u n t > 0 {
// t o u r n a m e n t . t o u r n a m e n t S t o r e ? . m a t c h e s . a d d O r U p d a t e ( c o n t e n t O f s : t o u r n a m e n t . _ a l l M a t c h e s I n c l u d i n g D i s a b l e d ( ) )
// }
// }
// }
}
}
} else if ( rebuildEverything = = false && requirements . contains ( . groupStage ) ) {
} else if ( rebuildEverything = = false && requirements . contains ( . groupStage ) ) {
tournament . deleteGroupStages ( )
tournament . deleteGroupStages ( )
@ -693,8 +650,63 @@ struct TableStructureView: View {
}
}
}
}
private func _handleSeedRepartition ( ) async {
while tournament . rounds ( ) . count < seedRepartition . count {
await tournament . addNewRound ( tournament . rounds ( ) . count )
}
if seedRepartition . reduce ( 0 , + ) > 0 {
let rounds = tournament . rounds ( )
let roundsToDelete = rounds . suffix ( rounds . count - seedRepartition . count )
for round in roundsToDelete {
await tournament . removeRound ( round )
}
}
for ( index , seedCount ) in seedRepartition . enumerated ( ) {
if let round = tournament . rounds ( ) . first ( where : { $0 . index = = index } ) {
let baseIndex = RoundRule . baseIndex ( forRoundIndex : round . index )
let numberOfMatches = RoundRule . numberOfMatches ( forRoundIndex : round . index )
let playedMatches = round . playedMatches ( ) . map { $0 . index - baseIndex }
let allMatches = round . _matches ( )
let seedSorted = frenchUmpireOrder ( for : numberOfMatches ) . filter ( { index in
playedMatches . contains ( index )
} ) . prefix ( seedCount )
for ( index , value ) in seedSorted . enumerated ( ) {
let isOpponentTurn = index >= playedMatches . count
if let match = allMatches [ safe : value ] {
if match . index - baseIndex < numberOfMatches / 2 {
if isOpponentTurn {
match . previousMatch ( . two ) ? . disableMatch ( )
} else {
match . previousMatch ( . one ) ? . disableMatch ( )
}
} else {
if isOpponentTurn {
match . previousMatch ( . one ) ? . disableMatch ( )
} else {
match . previousMatch ( . two ) ? . disableMatch ( )
}
}
}
}
if seedCount > 0 {
tournament . tournamentStore ? . matches . addOrUpdate ( contentOfs : round . _matches ( ) )
tournament . tournamentStore ? . matches . addOrUpdate ( contentOfs : round . allLoserRoundMatches ( ) )
round . deleteLoserBracket ( )
round . buildLoserBracket ( )
round . loserRounds ( ) . forEach { loserRound in
loserRound . disableUnplayedLoserBracketMatches ( )
}
}
}
}
}
private func _updatePreset ( ) {
private func _updatePreset ( ) {
if let selectedTournament {
if let selectedTournament {
seedRepartition = [ ]
teamCount = selectedTournament . teamCount
teamCount = selectedTournament . teamCount
groupStageCount = selectedTournament . groupStageCount
groupStageCount = selectedTournament . groupStageCount
teamsPerGroupStage = selectedTournament . teamsPerGroupStage
teamsPerGroupStage = selectedTournament . teamsPerGroupStage
@ -709,6 +721,7 @@ struct TableStructureView: View {
groupStageAdditionalQualified = 0
groupStageAdditionalQualified = 0
buildWildcards = tournament . level . wildcardArePossible ( )
buildWildcards = tournament . level . wildcardArePossible ( )
}
}
_verifyValueIntegrity ( )
}
}
private func _verifyValueIntegrity ( ) {
private func _verifyValueIntegrity ( ) {
@ -754,6 +767,7 @@ struct TableStructureView: View {
}
}
}
}
seedRepartition = HeadManagerView . place ( heads : tsPure , teamsInBracket : tf , initialSeedRound : nil )
}
}
}
}