|
|
|
|
@ -19,8 +19,9 @@ struct TableStructureView: View { |
|
|
|
|
@State private var qualifiedPerGroupStage: Int = 0 |
|
|
|
|
@State private var groupStageAdditionalQualified: Int = 0 |
|
|
|
|
@State private var updatedElements: Set<StructureElement> = Set() |
|
|
|
|
@State private var structurePreset: PadelTournamentStructurePreset = .manual |
|
|
|
|
@FocusState private var stepperFieldIsFocused: Bool |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var qualifiedFromGroupStage: Int { |
|
|
|
|
groupStageCount * qualifiedPerGroupStage |
|
|
|
|
} |
|
|
|
|
@ -51,6 +52,37 @@ struct TableStructureView: View { |
|
|
|
|
@ViewBuilder |
|
|
|
|
var body: some View { |
|
|
|
|
List { |
|
|
|
|
|
|
|
|
|
if tournament.state() != .build { |
|
|
|
|
Section { |
|
|
|
|
Picker(selection: $structurePreset) { |
|
|
|
|
ForEach(PadelTournamentStructurePreset.allCases) { preset in |
|
|
|
|
Text(preset.localizedStructurePresetTitle()).tag(preset) |
|
|
|
|
} |
|
|
|
|
} label: { |
|
|
|
|
Text("Préréglage") |
|
|
|
|
} |
|
|
|
|
} footer: { |
|
|
|
|
Text(structurePreset.localizedDescriptionStructurePresetTitle()) |
|
|
|
|
} |
|
|
|
|
.onChange(of: structurePreset) { |
|
|
|
|
switch structurePreset { |
|
|
|
|
case .manual: |
|
|
|
|
teamCount = 24 |
|
|
|
|
groupStageCount = 4 |
|
|
|
|
teamsPerGroupStage = 4 |
|
|
|
|
qualifiedPerGroupStage = 1 |
|
|
|
|
groupStageAdditionalQualified = 0 |
|
|
|
|
case .doubleGroupStage: |
|
|
|
|
teamCount = 9 |
|
|
|
|
groupStageCount = 3 |
|
|
|
|
teamsPerGroupStage = 3 |
|
|
|
|
qualifiedPerGroupStage = 0 |
|
|
|
|
groupStageAdditionalQualified = 0 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Section { |
|
|
|
|
LabeledContent { |
|
|
|
|
StepperView(count: $teamCount, minimum: 4, maximum: 128) |
|
|
|
|
@ -73,33 +105,62 @@ struct TableStructureView: View { |
|
|
|
|
Text("Équipes par poule") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
LabeledContent { |
|
|
|
|
StepperView(count: $qualifiedPerGroupStage, minimum: 1, maximum: (teamsPerGroupStage-1)) |
|
|
|
|
} label: { |
|
|
|
|
Text("Qualifiés par poule") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if qualifiedPerGroupStage < teamsPerGroupStage - 1 { |
|
|
|
|
if structurePreset == .manual { |
|
|
|
|
LabeledContent { |
|
|
|
|
StepperView(count: $groupStageAdditionalQualified, minimum: 0, maximum: maxMoreQualified) |
|
|
|
|
StepperView(count: $qualifiedPerGroupStage, minimum: 1, maximum: (teamsPerGroupStage-1)) |
|
|
|
|
} label: { |
|
|
|
|
Text("Qualifiés supplémentaires") |
|
|
|
|
Text(moreQualifiedLabel) |
|
|
|
|
Text("Qualifiés par poule") |
|
|
|
|
} |
|
|
|
|
.onChange(of: groupStageAdditionalQualified) { |
|
|
|
|
if groupStageAdditionalQualified == groupStageCount { |
|
|
|
|
qualifiedPerGroupStage += 1 |
|
|
|
|
groupStageAdditionalQualified -= groupStageCount |
|
|
|
|
|
|
|
|
|
if qualifiedPerGroupStage < teamsPerGroupStage - 1 { |
|
|
|
|
LabeledContent { |
|
|
|
|
StepperView(count: $groupStageAdditionalQualified, minimum: 0, maximum: maxMoreQualified) |
|
|
|
|
} label: { |
|
|
|
|
Text("Qualifiés supplémentaires") |
|
|
|
|
Text(moreQualifiedLabel) |
|
|
|
|
} |
|
|
|
|
.onChange(of: groupStageAdditionalQualified) { |
|
|
|
|
if groupStageAdditionalQualified == groupStageCount { |
|
|
|
|
qualifiedPerGroupStage += 1 |
|
|
|
|
groupStageAdditionalQualified -= groupStageCount |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if groupStageCount > 0 && teamsPerGroupStage > 0 { |
|
|
|
|
LabeledContent { |
|
|
|
|
let mp = teamsPerGroupStage * (teamsPerGroupStage - 1) / 2 |
|
|
|
|
Text(mp.formatted()) |
|
|
|
|
} label: { |
|
|
|
|
Text("Matchs à jouer par poule") |
|
|
|
|
if structurePreset == .manual { |
|
|
|
|
LabeledContent { |
|
|
|
|
let mp = teamsPerGroupStage * (teamsPerGroupStage - 1) / 2 |
|
|
|
|
Text(mp.formatted()) |
|
|
|
|
} label: { |
|
|
|
|
Text("Matchs à jouer par poule") |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
LabeledContent { |
|
|
|
|
let mp = teamsPerGroupStage * (teamsPerGroupStage - 1) / 2 |
|
|
|
|
Text(mp.formatted()) |
|
|
|
|
} label: { |
|
|
|
|
Text("Matchs à jouer par poule") |
|
|
|
|
Text("Première phase") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
LabeledContent { |
|
|
|
|
let mp = (groupStageCount * (groupStageCount - 1) / 2) |
|
|
|
|
Text(mp.formatted()) |
|
|
|
|
} label: { |
|
|
|
|
Text("Matchs à jouer par poule") |
|
|
|
|
Text("Deuxième phase") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
LabeledContent { |
|
|
|
|
let mp = groupStageCount - 1 + teamsPerGroupStage - 1 |
|
|
|
|
Text(mp.formatted()) |
|
|
|
|
} label: { |
|
|
|
|
Text("Matchs à jouer par équipe") |
|
|
|
|
Text("Total") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -116,22 +177,30 @@ struct TableStructureView: View { |
|
|
|
|
} label: { |
|
|
|
|
Text("Équipes en poule") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if structurePreset == .manual { |
|
|
|
|
|
|
|
|
|
LabeledContent { |
|
|
|
|
Text((qualifiedFromGroupStage + (groupStageCount > 0 ? groupStageAdditionalQualified : 0)).formatted()) |
|
|
|
|
} label: { |
|
|
|
|
Text("Équipes qualifiées de poule") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if structurePreset == .manual { |
|
|
|
|
|
|
|
|
|
LabeledContent { |
|
|
|
|
Text((qualifiedFromGroupStage + (groupStageCount > 0 ? groupStageAdditionalQualified : 0)).formatted()) |
|
|
|
|
let tsPure = max(teamCount - groupStageCount * teamsPerGroupStage, 0) |
|
|
|
|
Text(tsPure.formatted()) |
|
|
|
|
} label: { |
|
|
|
|
Text("Équipes qualifiées de poule") |
|
|
|
|
Text("Nombre de têtes de série") |
|
|
|
|
} |
|
|
|
|
LabeledContent { |
|
|
|
|
Text(tf.formatted()) |
|
|
|
|
} label: { |
|
|
|
|
Text("Équipes en tableau final") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
LabeledContent { |
|
|
|
|
let tsPure = max(teamCount - groupStageCount * teamsPerGroupStage, 0) |
|
|
|
|
Text(tsPure.formatted()) |
|
|
|
|
} label: { |
|
|
|
|
Text("Nombre de têtes de série") |
|
|
|
|
} |
|
|
|
|
LabeledContent { |
|
|
|
|
Text(tf.formatted()) |
|
|
|
|
} label: { |
|
|
|
|
Text("Équipes en tableau final") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -154,6 +223,13 @@ struct TableStructureView: View { |
|
|
|
|
_save(rebuildEverything: true) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Section { |
|
|
|
|
RowButtonView("Remise-à-zéro", role: .destructive) { |
|
|
|
|
tournament.deleteGroupStages() |
|
|
|
|
tournament.deleteStructure() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
.focused($stepperFieldIsFocused) |
|
|
|
|
@ -283,7 +359,7 @@ struct TableStructureView: View { |
|
|
|
|
tournament.groupStageAdditionalQualified = groupStageAdditionalQualified |
|
|
|
|
|
|
|
|
|
if rebuildEverything { |
|
|
|
|
tournament.deleteAndBuildEverything() |
|
|
|
|
tournament.deleteAndBuildEverything(preset: structurePreset) |
|
|
|
|
} else if (rebuildEverything == false && requirements.contains(.groupStage)) { |
|
|
|
|
tournament.deleteGroupStages() |
|
|
|
|
tournament.buildGroupStages() |
|
|
|
|
|